in arrow/cdata/cdata.go [141:252]
func importSchema(schema *CArrowSchema) (ret arrow.Field, err error) {
// always release, even on error
defer C.ArrowSchemaRelease(schema)
var childFields []arrow.Field
if schema.n_children > 0 {
// call ourselves recursively if there are children.
var schemaChildren []*CArrowSchema
// set up a slice to reference safely
s := (*reflect.SliceHeader)(unsafe.Pointer(&schemaChildren))
s.Data = uintptr(unsafe.Pointer(schema.children))
s.Len = int(schema.n_children)
s.Cap = int(schema.n_children)
childFields = make([]arrow.Field, schema.n_children)
for i, c := range schemaChildren {
childFields[i], err = importSchema((*CArrowSchema)(c))
if err != nil {
return
}
}
}
// copy the schema name from the c-string
ret.Name = C.GoString(schema.name)
ret.Nullable = (schema.flags & C.ARROW_FLAG_NULLABLE) != 0
ret.Metadata = decodeCMetadata(schema.metadata)
// copies the c-string here, but it's very small
f := C.GoString(schema.format)
// handle our non-parameterized simple types.
dt, ok := formatToSimpleType[f]
if ok {
ret.Type = dt
return
}
// handle types with params via colon
typs := strings.Split(f, ":")
defaulttz := "UTC"
switch typs[0] {
case "tss":
tz := typs[1]
if len(typs[1]) == 0 {
tz = defaulttz
}
dt = &arrow.TimestampType{Unit: arrow.Second, TimeZone: tz}
case "tsm":
tz := typs[1]
if len(typs[1]) == 0 {
tz = defaulttz
}
dt = &arrow.TimestampType{Unit: arrow.Millisecond, TimeZone: tz}
case "tsu":
tz := typs[1]
if len(typs[1]) == 0 {
tz = defaulttz
}
dt = &arrow.TimestampType{Unit: arrow.Microsecond, TimeZone: tz}
case "tsn":
tz := typs[1]
if len(typs[1]) == 0 {
tz = defaulttz
}
dt = &arrow.TimestampType{Unit: arrow.Nanosecond, TimeZone: tz}
case "w": // fixed size binary is "w:##" where ## is the byteWidth
byteWidth, err := strconv.Atoi(typs[1])
if err != nil {
return ret, err
}
dt = &arrow.FixedSizeBinaryType{ByteWidth: byteWidth}
case "d": // decimal types are d:<precision>,<scale>[,<bitsize>] size is assumed 128 if left out
props := typs[1]
propList := strings.Split(props, ",")
if len(propList) == 3 {
err = xerrors.New("only decimal128 is supported")
return
}
precision, _ := strconv.Atoi(propList[0])
scale, _ := strconv.Atoi(propList[1])
dt = &arrow.Decimal128Type{Precision: int32(precision), Scale: int32(scale)}
}
if f[0] == '+' { // types with children
switch f[1] {
case 'l': // list
dt = arrow.ListOfField(childFields[0])
case 'w': // fixed size list is w:# where # is the list size.
listSize, err := strconv.Atoi(strings.Split(f, ":")[1])
if err != nil {
return ret, err
}
dt = arrow.FixedSizeListOfField(int32(listSize), childFields[0])
case 's': // struct
dt = arrow.StructOf(childFields...)
case 'm': // map type is basically a list of structs.
st := childFields[0].Type.(*arrow.StructType)
dt = arrow.MapOf(st.Field(0).Type, st.Field(1).Type)
dt.(*arrow.MapType).KeysSorted = (schema.flags & C.ARROW_FLAG_MAP_KEYS_SORTED) != 0
}
}
if dt == nil {
// if we didn't find a type, then it's something we haven't implemented.
err = xerrors.New("unimplemented type")
} else {
ret.Type = dt
}
return
}