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