in arrow/cdata/cdata.go [475:655]
func (imp *cimporter) doImport() error {
// move the array from the src object passed in to the one referenced by
// this importer. That way we can set up a finalizer on the created
// arrow.ArrayData object so we clean up our Array's memory when garbage collected.
defer func(arr *CArrowArray) {
// this should only occur in the case of an error happening
// during import, at which point we need to clean up the
// ArrowArray struct we allocated.
if imp.data == nil {
C.free(unsafe.Pointer(arr))
}
}(imp.arr)
// import any children
if err := imp.doImportChildren(); err != nil {
return err
}
for _, c := range imp.children {
if c.data != nil {
defer c.data.Release()
}
}
if imp.arr.n_buffers > 0 {
// get a view of the buffers, zero-copy. we're just looking at the pointers
imp.cbuffers = unsafe.Slice((**C.void)(unsafe.Pointer(imp.arr.buffers)), imp.arr.n_buffers)
}
// handle each of our type cases
switch dt := imp.dt.(type) {
case *arrow.NullType:
if err := imp.checkNoChildren(); err != nil {
return err
}
imp.data = array.NewData(dt, int(imp.arr.length), nil, nil, int(imp.arr.null_count), int(imp.arr.offset))
case arrow.FixedWidthDataType:
return imp.importFixedSizePrimitive()
case *arrow.StringType:
return imp.importStringLike(int64(arrow.Int32SizeBytes))
case *arrow.BinaryType:
return imp.importStringLike(int64(arrow.Int32SizeBytes))
case *arrow.LargeStringType:
return imp.importStringLike(int64(arrow.Int64SizeBytes))
case *arrow.LargeBinaryType:
return imp.importStringLike(int64(arrow.Int64SizeBytes))
case *arrow.StringViewType:
return imp.importBinaryViewLike()
case *arrow.BinaryViewType:
return imp.importBinaryViewLike()
case *arrow.ListType:
return imp.importListLike()
case *arrow.LargeListType:
return imp.importListLike()
case *arrow.ListViewType:
return imp.importListViewLike()
case *arrow.LargeListViewType:
return imp.importListViewLike()
case *arrow.MapType:
return imp.importListLike()
case *arrow.FixedSizeListType:
if err := imp.checkNumChildren(1); err != nil {
return err
}
if err := imp.checkNumBuffers(1); err != nil {
return err
}
nulls, err := imp.importNullBitmap(0)
if err != nil {
return err
}
if nulls != nil {
defer nulls.Release()
}
imp.data = array.NewData(dt, int(imp.arr.length), []*memory.Buffer{nulls}, []arrow.ArrayData{imp.children[0].data}, int(imp.arr.null_count), int(imp.arr.offset))
case *arrow.StructType:
if err := imp.checkNumBuffers(1); err != nil {
return err
}
nulls, err := imp.importNullBitmap(0)
if err != nil {
return err
}
if nulls != nil {
defer nulls.Release()
}
children := make([]arrow.ArrayData, len(imp.children))
for i := range imp.children {
children[i] = imp.children[i].data
}
imp.data = array.NewData(dt, int(imp.arr.length), []*memory.Buffer{nulls}, children, int(imp.arr.null_count), int(imp.arr.offset))
case *arrow.RunEndEncodedType:
if err := imp.checkNumBuffers(0); err != nil {
return err
}
if len(imp.children) != 2 {
return fmt.Errorf("%w: run-end encoded array should have 2 children", arrow.ErrInvalid)
}
children := []arrow.ArrayData{imp.children[0].data, imp.children[1].data}
imp.data = array.NewData(dt, int(imp.arr.length), []*memory.Buffer{}, children, int(imp.arr.null_count), int(imp.arr.offset))
case *arrow.DenseUnionType:
if err := imp.checkNoNulls(); err != nil {
return err
}
bufs := []*memory.Buffer{nil, nil, nil}
var err error
if imp.arr.n_buffers == 3 {
// legacy format exported by older arrow c++ versions
if bufs[1], err = imp.importFixedSizeBuffer(1, 1); err != nil {
return err
}
defer bufs[1].Release()
if bufs[2], err = imp.importFixedSizeBuffer(2, int64(arrow.Int32SizeBytes)); err != nil {
return err
}
defer bufs[2].Release()
} else {
if err := imp.checkNumBuffers(2); err != nil {
return err
}
if bufs[1], err = imp.importFixedSizeBuffer(0, 1); err != nil {
return err
}
defer bufs[1].Release()
if bufs[2], err = imp.importFixedSizeBuffer(1, int64(arrow.Int32SizeBytes)); err != nil {
return err
}
defer bufs[2].Release()
}
children := make([]arrow.ArrayData, len(imp.children))
for i := range imp.children {
children[i] = imp.children[i].data
}
imp.data = array.NewData(dt, int(imp.arr.length), bufs, children, 0, int(imp.arr.offset))
case *arrow.SparseUnionType:
if err := imp.checkNoNulls(); err != nil {
return err
}
var buf *memory.Buffer
var err error
if imp.arr.n_buffers == 2 {
// legacy format exported by older Arrow C++ versions
if buf, err = imp.importFixedSizeBuffer(1, 1); err != nil {
return err
}
defer buf.Release()
} else {
if err := imp.checkNumBuffers(1); err != nil {
return err
}
if buf, err = imp.importFixedSizeBuffer(0, 1); err != nil {
return err
}
defer buf.Release()
}
children := make([]arrow.ArrayData, len(imp.children))
for i := range imp.children {
children[i] = imp.children[i].data
}
imp.data = array.NewData(dt, int(imp.arr.length), []*memory.Buffer{nil, buf}, children, 0, int(imp.arr.offset))
default:
return fmt.Errorf("unimplemented type %s", dt)
}
return nil
}