1 // Licensed to the Apache Software Foundation (ASF) under one or more 2 // contributor license agreements. See the NOTICE file distributed with 3 // this work for additional information regarding copyright ownership. 4 // The ASF licenses this file to You under the Apache License, Version 2.0 5 // (the "License"); you may not use this file except in compliance with 6 // the License. You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 16 using System; 17 using System.IO; 18 19 namespace Apache.Arrow.Ipc 20 { 21 internal class MessageSerializer 22 { 23 public const int IpcContinuationToken = -1; 24 GetNumberType(int bitWidth, bool signed)25 public static Types.NumberType GetNumberType(int bitWidth, bool signed) 26 { 27 if (signed) 28 { 29 if (bitWidth == 8) 30 return Types.Int8Type.Default; 31 if (bitWidth == 16) 32 return Types.Int16Type.Default; 33 if (bitWidth == 32) 34 return Types.Int32Type.Default; 35 if (bitWidth == 64) 36 return Types.Int64Type.Default; 37 } 38 else 39 { 40 if (bitWidth == 8) 41 return Types.UInt8Type.Default; 42 if (bitWidth == 16) 43 return Types.UInt16Type.Default; 44 if (bitWidth == 32) 45 return Types.UInt32Type.Default; 46 if (bitWidth == 64) 47 return Types.UInt64Type.Default; 48 } 49 throw new Exception($"Unexpected bit width of {bitWidth} for " + 50 $"{(signed ? "signed " : "unsigned")} integer."); 51 } 52 GetSchema(Flatbuf.Schema schema)53 internal static Schema GetSchema(Flatbuf.Schema schema) 54 { 55 var schemaBuilder = new Schema.Builder(); 56 57 for (int i = 0; i < schema.FieldsLength; i++) 58 { 59 Flatbuf.Field field = schema.Fields(i).GetValueOrDefault(); 60 61 schemaBuilder.Field( 62 new Field(field.Name, GetFieldArrowType(field), field.Nullable)); 63 } 64 65 return schemaBuilder.Build(); 66 } 67 68 GetFieldArrowType(Flatbuf.Field field)69 private static Types.IArrowType GetFieldArrowType(Flatbuf.Field field) 70 { 71 switch (field.TypeType) 72 { 73 case Flatbuf.Type.Int: 74 Flatbuf.Int intMetaData = field.Type<Flatbuf.Int>().Value; 75 return MessageSerializer.GetNumberType(intMetaData.BitWidth, intMetaData.IsSigned); 76 case Flatbuf.Type.FloatingPoint: 77 Flatbuf.FloatingPoint floatingPointTypeMetadata = field.Type<Flatbuf.FloatingPoint>().Value; 78 switch (floatingPointTypeMetadata.Precision) 79 { 80 case Flatbuf.Precision.SINGLE: 81 return Types.FloatType.Default; 82 case Flatbuf.Precision.DOUBLE: 83 return Types.DoubleType.Default; 84 case Flatbuf.Precision.HALF: 85 return Types.HalfFloatType.Default; 86 default: 87 throw new InvalidDataException("Unsupported floating point precision"); 88 } 89 case Flatbuf.Type.Bool: 90 return new Types.BooleanType(); 91 case Flatbuf.Type.Decimal: 92 Flatbuf.Decimal decMeta = field.Type<Flatbuf.Decimal>().Value; 93 return new Types.DecimalType(decMeta.Precision, decMeta.Scale); 94 case Flatbuf.Type.Date: 95 Flatbuf.Date dateMeta = field.Type<Flatbuf.Date>().Value; 96 switch (dateMeta.Unit) 97 { 98 case Flatbuf.DateUnit.DAY: 99 return Types.Date32Type.Default; 100 case Flatbuf.DateUnit.MILLISECOND: 101 return Types.Date64Type.Default; 102 default: 103 throw new InvalidDataException("Unsupported date unit"); 104 } 105 case Flatbuf.Type.Time: 106 Flatbuf.Time timeMeta = field.Type<Flatbuf.Time>().Value; 107 switch (timeMeta.BitWidth) 108 { 109 case 32: 110 return new Types.Time32Type(timeMeta.Unit.ToArrow()); 111 case 64: 112 return new Types.Time64Type(timeMeta.Unit.ToArrow()); 113 default: 114 throw new InvalidDataException("Unsupported time bit width"); 115 } 116 case Flatbuf.Type.Timestamp: 117 Flatbuf.Timestamp timestampTypeMetadata = field.Type<Flatbuf.Timestamp>().Value; 118 Types.TimeUnit unit = timestampTypeMetadata.Unit.ToArrow(); 119 string timezone = timestampTypeMetadata.Timezone; 120 return new Types.TimestampType(unit, timezone); 121 case Flatbuf.Type.Interval: 122 Flatbuf.Interval intervalMetadata = field.Type<Flatbuf.Interval>().Value; 123 return new Types.IntervalType(intervalMetadata.Unit.ToArrow()); 124 case Flatbuf.Type.Utf8: 125 return new Types.StringType(); 126 case Flatbuf.Type.Binary: 127 return Types.BinaryType.Default; 128 case Flatbuf.Type.List: 129 if (field.ChildrenLength != 1) 130 { 131 throw new InvalidDataException($"List type must have only one child."); 132 } 133 return new Types.ListType(GetFieldArrowType(field.Children(0).GetValueOrDefault())); 134 default: 135 throw new InvalidDataException($"Arrow primitive '{field.TypeType}' is unsupported."); 136 } 137 } 138 } 139 } 140