nanoarrow 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,204 @@
1
+ #include <ruby/ruby.h>
2
+
3
+ #include "ext.h"
4
+ #include "nanoarrow/nanoarrow.h"
5
+
6
+ VALUE cCSchemaView;
7
+
8
+ typedef struct schema_view {
9
+ VALUE base;
10
+ struct ArrowSchemaView schema_view;
11
+ int nullable;
12
+ } schema_view_t;
13
+
14
+ static void schema_view_mark(void* ptr)
15
+ {
16
+ schema_view_t* view = (schema_view_t*) ptr;
17
+ rb_gc_mark_movable(view->base);
18
+ }
19
+
20
+ const rb_data_type_t schema_view_data_type = {
21
+ .wrap_struct_name = "Nanoarrow::CSchemaView",
22
+ .function = {
23
+ .dmark = schema_view_mark,
24
+ .dfree = RUBY_TYPED_DEFAULT_FREE,
25
+ },
26
+ .flags = RUBY_TYPED_FREE_IMMEDIATELY
27
+ };
28
+
29
+ VALUE schema_view_allocate(VALUE klass)
30
+ {
31
+ schema_view_t* view;
32
+ VALUE obj = TypedData_Make_Struct(klass, schema_view_t, &schema_view_data_type, view);
33
+ view->base = Qnil;
34
+ view->schema_view.type = NANOARROW_TYPE_UNINITIALIZED;
35
+ view->schema_view.storage_type = NANOARROW_TYPE_UNINITIALIZED;
36
+ view->nullable = 0;
37
+ return obj;
38
+ }
39
+
40
+ VALUE schema_view_initialize(VALUE self, VALUE schema)
41
+ {
42
+ schema_view_t* view;
43
+ GetSchemaView(self, view);
44
+
45
+ view->base = schema;
46
+ view->schema_view.type = NANOARROW_TYPE_UNINITIALIZED;
47
+ view->schema_view.storage_type = NANOARROW_TYPE_UNINITIALIZED;
48
+
49
+ schema_t* schema_ptr;
50
+ GetSchema(schema, schema_ptr);
51
+
52
+ struct ArrowError error;
53
+ int code = ArrowSchemaViewInit(&view->schema_view, schema_ptr->ptr, &error);
54
+ raise_message_not_ok(&error, "ArrowSchemaViewInit()", code);
55
+
56
+ view->nullable = schema_ptr->ptr->flags & ARROW_FLAG_NULLABLE;
57
+
58
+ return self;
59
+ }
60
+
61
+ VALUE schema_view_type_id(VALUE self)
62
+ {
63
+ schema_view_t* view;
64
+ GetSchemaView(self, view);
65
+
66
+ return INT2NUM(view->schema_view.type);
67
+ }
68
+
69
+ VALUE schema_view_storage_type_id(VALUE self)
70
+ {
71
+ schema_view_t* view;
72
+ GetSchemaView(self, view);
73
+
74
+ return INT2NUM(view->schema_view.storage_type);
75
+ }
76
+
77
+ VALUE schema_view_type(VALUE self)
78
+ {
79
+ schema_view_t* view;
80
+ GetSchemaView(self, view);
81
+
82
+ const char* type_str = ArrowTypeString(view->schema_view.type);
83
+ if (type_str != NULL)
84
+ return rb_utf8_str_new_cstr(type_str);
85
+ else
86
+ rb_raise(rb_eArgError, "ArrowTypeString() returned NULL");
87
+ }
88
+
89
+ VALUE schema_view_nullable(VALUE self)
90
+ {
91
+ schema_view_t* view;
92
+ GetSchemaView(self, view);
93
+
94
+ return view->nullable != 0 ? Qtrue : Qfalse;
95
+ }
96
+
97
+ bool is_fixed_size(int type)
98
+ {
99
+ switch (type)
100
+ {
101
+ case NANOARROW_TYPE_FIXED_SIZE_BINARY:
102
+ case NANOARROW_TYPE_FIXED_SIZE_LIST:
103
+ return true;
104
+ default:
105
+ return false;
106
+ }
107
+ }
108
+
109
+ bool is_decimal(int type)
110
+ {
111
+ switch (type)
112
+ {
113
+ case NANOARROW_TYPE_DECIMAL128:
114
+ case NANOARROW_TYPE_DECIMAL256:
115
+ return true;
116
+ default:
117
+ return false;
118
+ }
119
+ }
120
+
121
+ bool has_time_unit(int type)
122
+ {
123
+ switch (type)
124
+ {
125
+ case NANOARROW_TYPE_TIME32:
126
+ case NANOARROW_TYPE_TIME64:
127
+ case NANOARROW_TYPE_TIMESTAMP:
128
+ case NANOARROW_TYPE_DURATION:
129
+ return true;
130
+ default:
131
+ return false;
132
+ }
133
+ }
134
+
135
+ VALUE schema_view_fixed_size(VALUE self)
136
+ {
137
+ schema_view_t* view;
138
+ GetSchemaView(self, view);
139
+
140
+ if (is_fixed_size(view->schema_view.type))
141
+ return INT2NUM(view->schema_view.fixed_size);
142
+ else
143
+ return Qnil;
144
+ }
145
+
146
+ VALUE schema_view_decimal_precision(VALUE self)
147
+ {
148
+ schema_view_t* view;
149
+ GetSchemaView(self, view);
150
+
151
+ if (is_decimal(view->schema_view.type))
152
+ return INT2NUM(view->schema_view.decimal_precision);
153
+ else
154
+ return Qnil;
155
+ }
156
+
157
+ VALUE schema_view_decimal_scale(VALUE self)
158
+ {
159
+ schema_view_t* view;
160
+ GetSchemaView(self, view);
161
+
162
+ if (is_decimal(view->schema_view.type))
163
+ return INT2NUM(view->schema_view.decimal_scale);
164
+ else
165
+ return Qnil;
166
+ }
167
+
168
+ VALUE schema_view_time_unit(VALUE self)
169
+ {
170
+ schema_view_t* view;
171
+ GetSchemaView(self, view);
172
+
173
+ if (has_time_unit(view->schema_view.type))
174
+ return rb_utf8_str_new_cstr(ArrowTimeUnitString(view->schema_view.time_unit));
175
+ else
176
+ return Qnil;
177
+ }
178
+
179
+ VALUE schema_view_timezone(VALUE self)
180
+ {
181
+ schema_view_t* view;
182
+ GetSchemaView(self, view);
183
+
184
+ if (view->schema_view.type == NANOARROW_TYPE_TIMESTAMP)
185
+ return rb_utf8_str_new_cstr(view->schema_view.timezone);
186
+ else
187
+ return Qnil;
188
+ }
189
+
190
+ void Init_schema_view(void)
191
+ {
192
+ cCSchemaView = rb_define_class_under(mNanoarrow, "CSchemaView", rb_cObject);
193
+ rb_define_alloc_func(cCSchemaView, schema_view_allocate);
194
+ rb_define_method(cCSchemaView, "initialize", schema_view_initialize, 1);
195
+ rb_define_method(cCSchemaView, "type_id", schema_view_type_id, 0);
196
+ rb_define_method(cCSchemaView, "storage_type_id", schema_view_storage_type_id, 0);
197
+ rb_define_method(cCSchemaView, "type", schema_view_type, 0);
198
+ rb_define_method(cCSchemaView, "nullable", schema_view_nullable, 0);
199
+ rb_define_method(cCSchemaView, "fixed_size", schema_view_fixed_size, 0);
200
+ rb_define_method(cCSchemaView, "decimal_precision", schema_view_decimal_precision, 0);
201
+ rb_define_method(cCSchemaView, "decimal_scale", schema_view_decimal_scale, 0);
202
+ rb_define_method(cCSchemaView, "time_unit", schema_view_time_unit, 0);
203
+ rb_define_method(cCSchemaView, "timezone", schema_view_timezone, 0);
204
+ }
@@ -0,0 +1,48 @@
1
+ #include <ruby/ruby.h>
2
+
3
+ #include "ext.h"
4
+ #include "nanoarrow/nanoarrow.h"
5
+
6
+ void Init_types(void)
7
+ {
8
+ VALUE mType = rb_define_module_under(mNanoarrow, "Type");
9
+ rb_define_const(mType, "NULL", INT2NUM(NANOARROW_TYPE_NA));
10
+ rb_define_const(mType, "BOOL", INT2NUM(NANOARROW_TYPE_BOOL));
11
+ rb_define_const(mType, "INT8", INT2NUM(NANOARROW_TYPE_INT8));
12
+ rb_define_const(mType, "UINT8", INT2NUM(NANOARROW_TYPE_UINT8));
13
+ rb_define_const(mType, "INT16", INT2NUM(NANOARROW_TYPE_INT16));
14
+ rb_define_const(mType, "UINT16", INT2NUM(NANOARROW_TYPE_UINT16));
15
+ rb_define_const(mType, "INT32", INT2NUM(NANOARROW_TYPE_INT32));
16
+ rb_define_const(mType, "UINT32", INT2NUM(NANOARROW_TYPE_UINT32));
17
+ rb_define_const(mType, "INT64", INT2NUM(NANOARROW_TYPE_INT64));
18
+ rb_define_const(mType, "UINT64", INT2NUM(NANOARROW_TYPE_UINT64));
19
+ rb_define_const(mType, "HALF_FLOAT", INT2NUM(NANOARROW_TYPE_HALF_FLOAT));
20
+ rb_define_const(mType, "FLOAT", INT2NUM(NANOARROW_TYPE_FLOAT));
21
+ rb_define_const(mType, "DOUBLE", INT2NUM(NANOARROW_TYPE_DOUBLE));
22
+ rb_define_const(mType, "STRING", INT2NUM(NANOARROW_TYPE_STRING));
23
+ rb_define_const(mType, "LARGE_STRING", INT2NUM(NANOARROW_TYPE_LARGE_STRING));
24
+ rb_define_const(mType, "STRING_VIEW", INT2NUM(NANOARROW_TYPE_STRING_VIEW));
25
+ rb_define_const(mType, "BINARY", INT2NUM(NANOARROW_TYPE_BINARY));
26
+ rb_define_const(mType, "LARGE_BINARY", INT2NUM(NANOARROW_TYPE_LARGE_BINARY));
27
+ rb_define_const(mType, "BINARY_VIEW", INT2NUM(NANOARROW_TYPE_BINARY_VIEW));
28
+ rb_define_const(mType, "FIXED_SIZE_BINARY", INT2NUM(NANOARROW_TYPE_FIXED_SIZE_BINARY));
29
+ rb_define_const(mType, "DATE32", INT2NUM(NANOARROW_TYPE_DATE32));
30
+ rb_define_const(mType, "DATE64", INT2NUM(NANOARROW_TYPE_DATE64));
31
+ rb_define_const(mType, "TIME32", INT2NUM(NANOARROW_TYPE_TIME32));
32
+ rb_define_const(mType, "TIME64", INT2NUM(NANOARROW_TYPE_TIME64));
33
+ rb_define_const(mType, "TIMESTAMP", INT2NUM(NANOARROW_TYPE_TIMESTAMP));
34
+ rb_define_const(mType, "DURATION", INT2NUM(NANOARROW_TYPE_DURATION));
35
+ rb_define_const(mType, "INTERVAL_MONTHS", INT2NUM(NANOARROW_TYPE_INTERVAL_MONTHS));
36
+ rb_define_const(mType, "INTERVAL_DAY_TIME", INT2NUM(NANOARROW_TYPE_INTERVAL_DAY_TIME));
37
+ rb_define_const(mType, "INTERVAL_MONTH_DAY_NANO", INT2NUM(NANOARROW_TYPE_INTERVAL_MONTH_DAY_NANO));
38
+ rb_define_const(mType, "DECIMAL128", INT2NUM(NANOARROW_TYPE_DECIMAL128));
39
+ rb_define_const(mType, "DECIMAL256", INT2NUM(NANOARROW_TYPE_DECIMAL256));
40
+ rb_define_const(mType, "STRUCT", INT2NUM(NANOARROW_TYPE_STRUCT));
41
+ rb_define_const(mType, "LIST", INT2NUM(NANOARROW_TYPE_LIST));
42
+ rb_define_const(mType, "LARGE_LIST", INT2NUM(NANOARROW_TYPE_LARGE_LIST));
43
+ rb_define_const(mType, "FIXED_SIZE_LIST", INT2NUM(NANOARROW_TYPE_FIXED_SIZE_LIST));
44
+ rb_define_const(mType, "MAP", INT2NUM(NANOARROW_TYPE_MAP));
45
+ rb_define_const(mType, "DICTIONARY", INT2NUM(NANOARROW_TYPE_DICTIONARY));
46
+ rb_define_const(mType, "SPARSE_UNION", INT2NUM(NANOARROW_TYPE_SPARSE_UNION));
47
+ rb_define_const(mType, "DENSE_UNION", INT2NUM(NANOARROW_TYPE_DENSE_UNION));
48
+ }
@@ -0,0 +1,202 @@
1
+ #include <ruby/ruby.h>
2
+
3
+ #include "ext.h"
4
+ #include "nanoarrow/nanoarrow.h"
5
+
6
+ void raise_todo(void)
7
+ {
8
+ rb_raise(rb_const_get(mNanoarrow, rb_intern("Todo")), "not implemented yet");
9
+ }
10
+
11
+ void raise_message_not_ok(struct ArrowError* error, const char* message, int code)
12
+ {
13
+ if (code != NANOARROW_OK)
14
+ rb_raise(rb_const_get(mNanoarrow, rb_intern("Error")), "%s", error->message);
15
+ }
16
+
17
+ void raise_error_not_ok(const char* message, int code)
18
+ {
19
+ if (code != NANOARROW_OK)
20
+ rb_raise(rb_const_get(mNanoarrow, rb_intern("Error")), "%s", message);
21
+ }
22
+
23
+ void array_deleter(void* ptr)
24
+ {
25
+ struct ArrowArray* array = (struct ArrowArray*) ptr;
26
+
27
+ if (array->release != NULL)
28
+ ArrowArrayRelease(array);
29
+
30
+ ArrowFree(array);
31
+ }
32
+
33
+ void rbcapsule_array_deleter(capsule_t* capsule)
34
+ {
35
+ rc_t* rc = capsule_pointer(capsule, "arrow_array");
36
+
37
+ if (rc == NULL)
38
+ return;
39
+
40
+ rc_decrement(rc);
41
+ }
42
+
43
+ VALUE alloc_c_array(struct ArrowArray** c_array)
44
+ {
45
+ *c_array = ArrowMalloc(sizeof(struct ArrowArray));
46
+ (*c_array)->release = NULL;
47
+ rc_t* rc = rc_new(*c_array, array_deleter);
48
+ return capsule_new(rc, "arrow_array", rbcapsule_array_deleter);
49
+ }
50
+
51
+ void rbcapsule_array_stream_deleter(capsule_t* capsule)
52
+ {
53
+ struct ArrowArrayStream* stream = capsule_pointer(capsule, "arrow_array_stream");
54
+
55
+ if (stream == NULL)
56
+ return;
57
+
58
+ if (stream->release != NULL)
59
+ ArrowArrayStreamRelease(stream);
60
+
61
+ ArrowFree(stream);
62
+ }
63
+
64
+ VALUE alloc_c_array_stream(struct ArrowArrayStream** c_stream)
65
+ {
66
+ *c_stream = ArrowMalloc(sizeof(struct ArrowArrayStream));
67
+ (*c_stream)->release = NULL;
68
+ return capsule_new(*c_stream, "arrow_array_stream", rbcapsule_array_stream_deleter);
69
+ }
70
+
71
+ void rbcapsule_array_view_deleter(capsule_t* capsule)
72
+ {
73
+ struct ArrowArrayView* array_view = capsule_pointer(capsule, "nanoarrow_array_view");
74
+
75
+ if (array_view == NULL)
76
+ return;
77
+
78
+ ArrowArrayViewReset(array_view);
79
+
80
+ ArrowFree(array_view);
81
+ }
82
+
83
+ VALUE alloc_c_array_view(struct ArrowArrayView** c_array_view)
84
+ {
85
+ *c_array_view = ArrowMalloc(sizeof(struct ArrowArrayView));
86
+ ArrowArrayViewInitFromType(*c_array_view, NANOARROW_TYPE_UNINITIALIZED);
87
+ return capsule_new(*c_array_view, "nanoarrow_array_view", rbcapsule_array_view_deleter);
88
+ }
89
+
90
+ void rbcapsule_buffer_deleter(capsule_t* capsule)
91
+ {
92
+ struct ArrowBuffer* buffer = capsule_pointer(capsule, "nanoarrow_buffer");
93
+
94
+ if (buffer == NULL)
95
+ return;
96
+
97
+ ArrowBufferReset(buffer);
98
+ ArrowFree(buffer);
99
+ }
100
+
101
+ VALUE alloc_c_buffer(struct ArrowBuffer** c_buffer)
102
+ {
103
+ *c_buffer = ArrowMalloc(sizeof(struct ArrowBuffer));
104
+ ArrowBufferInit(*c_buffer);
105
+ return capsule_new(*c_buffer, "nanoarrow_buffer", rbcapsule_buffer_deleter);
106
+ }
107
+
108
+ void rbcapsule_schema_deleter(capsule_t* capsule)
109
+ {
110
+ struct ArrowSchema* schema = capsule_pointer(capsule, "arrow_schema");
111
+
112
+ if (schema == NULL)
113
+ return;
114
+
115
+ if (schema->release != NULL)
116
+ ArrowSchemaRelease(schema);
117
+
118
+ ArrowFree(schema);
119
+ }
120
+
121
+ VALUE alloc_c_schema(struct ArrowSchema** c_schema)
122
+ {
123
+ *c_schema = ArrowMalloc(sizeof(struct ArrowSchema));
124
+ (*c_schema)->release = NULL;
125
+ return capsule_new(*c_schema, "arrow_schema", rbcapsule_schema_deleter);
126
+ }
127
+
128
+ void c_deallocate_rbobject_buffer(struct ArrowBufferAllocator* allocator, uint8_t* ptr, int64_t size)
129
+ {
130
+ rc_t* rc = allocator->private_data;
131
+ rc_decrement(rc);
132
+ }
133
+
134
+ void c_rbobject_buffer(VALUE base, const void* buf, int64_t size_bytes, struct ArrowBuffer* out)
135
+ {
136
+ out->data = (void*) buf;
137
+ out->size_bytes = size_bytes;
138
+
139
+ capsule_t* capsule;
140
+ GetCapsule(base, capsule);
141
+ rc_t* rc = capsule_pointer(capsule, "arrow_array");
142
+
143
+ if (rc == NULL)
144
+ rb_raise(rb_eRuntimeError, "cannot open capsule");
145
+
146
+ rc_increment(rc);
147
+
148
+ // since buffers can be moved by receiver (non-Ruby code), need to reference count
149
+ // and only destroy C array when no more references (this can be long after Ruby object is GCed)
150
+ out->allocator = ArrowBufferDeallocator(c_deallocate_rbobject_buffer, rc);
151
+ }
152
+
153
+ void c_array_shallow_copy(VALUE base, const struct ArrowArray* src, struct ArrowArray* dst)
154
+ {
155
+ struct ArrowArray* tmp;
156
+ VALUE shelter = alloc_c_array(&tmp);
157
+ int code;
158
+
159
+ code = ArrowArrayInitFromType(tmp, NANOARROW_TYPE_UNINITIALIZED);
160
+ raise_error_not_ok("ArrowArrayInitFromType()", code);
161
+
162
+ tmp->length = src->length;
163
+ tmp->offset = src->offset;
164
+ tmp->null_count = src->null_count;
165
+
166
+ if (src->n_buffers > 3)
167
+ {
168
+ code = ArrowArrayAddVariadicBuffers(dst, src->n_buffers - 3);
169
+ raise_error_not_ok("ArrowArrayAddVariadicBuffers()", code);
170
+ }
171
+
172
+ for (int64_t i = 0; i < src->n_buffers; i++)
173
+ {
174
+ if (src->buffers[i] != NULL)
175
+ c_rbobject_buffer(base, src->buffers[i], 0, ArrowArrayBuffer(tmp, i));
176
+
177
+ tmp->buffers[i] = src->buffers[i];
178
+ }
179
+
180
+ tmp->n_buffers = src->n_buffers;
181
+
182
+ if (src->n_children > 0)
183
+ {
184
+ code = ArrowArrayAllocateChildren(tmp, src->n_children);
185
+ raise_error_not_ok("ArrowArrayAllocateChildren()", code);
186
+
187
+ for (int64_t i = 0; i < src->n_children; i++)
188
+ c_array_shallow_copy(base, src->children[i], tmp->children[i]);
189
+ }
190
+
191
+ if (src->dictionary != NULL)
192
+ {
193
+ code = ArrowArrayAllocateDictionary(tmp);
194
+ raise_error_not_ok("ArrowArrayAllocateDictionary()", code);
195
+
196
+ c_array_shallow_copy(base, src->dictionary, tmp->dictionary);
197
+ }
198
+
199
+ ArrowArrayMove(tmp, dst);
200
+
201
+ (void) shelter;
202
+ }
@@ -0,0 +1,97 @@
1
+ module Nanoarrow
2
+ class Array
3
+ def initialize(obj, schema = nil)
4
+ if obj.is_a?(CMaterializedArrayStream) && schema.nil?
5
+ @data = obj
6
+ return
7
+ end
8
+
9
+ if obj.is_a?(Array) && schema.nil?
10
+ @data = obj.instance_variable_get(:@data)
11
+ return
12
+ end
13
+
14
+ if obj.is_a?(CArray) && schema.nil?
15
+ @data = CMaterializedArrayStream.from_c_array(obj)
16
+ return
17
+ end
18
+
19
+ stream = Utils.c_array_stream(obj, schema)
20
+ @data = CMaterializedArrayStream.from_c_array_stream(stream)
21
+ end
22
+
23
+ def self.from_chunks(obj, schema = nil, validate: true)
24
+ if schema.nil?
25
+ raise Todo
26
+ else
27
+ out_schema = Utils.c_schema(schema)
28
+ end
29
+
30
+ data =
31
+ CMaterializedArrayStream.from_c_arrays(
32
+ obj.map { |item| Utils.c_array(item, schema) },
33
+ out_schema,
34
+ validate
35
+ )
36
+
37
+ Array.new(data)
38
+ end
39
+
40
+ def arrow_c_stream
41
+ @data.arrow_c_stream
42
+ end
43
+
44
+ def schema
45
+ Schema.new(@data.schema)
46
+ end
47
+
48
+ def n_children
49
+ @data.schema.n_children
50
+ end
51
+
52
+ def child(i)
53
+ Array.new(@data.child(i))
54
+ end
55
+
56
+ def each_child
57
+ return to_enum(:each_child) unless block_given?
58
+
59
+ n_children.times do |i|
60
+ yield child(i)
61
+ end
62
+ end
63
+
64
+ def n_chunks
65
+ @data.n_arrays
66
+ end
67
+
68
+ def chunk(i)
69
+ Array.new(@data.array(i))
70
+ end
71
+
72
+ def each_chunk
73
+ return to_enum(:each_chunk) unless block_given?
74
+
75
+ n_chunks.times do |i|
76
+ yield chunk(i)
77
+ end
78
+ end
79
+
80
+ def length
81
+ @data.length
82
+ end
83
+ alias_method :size, :length
84
+
85
+ def each
86
+ RbIterator.get_iterator(self)
87
+ end
88
+
89
+ def to_a
90
+ each.to_a
91
+ end
92
+
93
+ def inspect
94
+ "#<#{self.class.name} #{schema.inspect}[#{length.inspect}]>"
95
+ end
96
+ end
97
+ end
@@ -0,0 +1,115 @@
1
+ module Nanoarrow
2
+ class ArrayBuilder
3
+ def initialize(schema)
4
+ @schema = Utils.c_schema(schema)
5
+ @schema_view = Utils.c_schema_view(@schema)
6
+ @c_builder = CArrayBuilder.allocate
7
+ @c_builder.init_from_schema(@schema)
8
+ end
9
+
10
+ def build_c_array(obj)
11
+ start_building
12
+ append(obj)
13
+ finish_building
14
+ end
15
+ end
16
+
17
+ class ArrayFromIterableBuilder < ArrayBuilder
18
+ def initialize(schema)
19
+ super(schema)
20
+
21
+ type_id = @schema_view.type_id
22
+ if !ARRAY_BUILDER_FROM_ITERABLE_METHOD.include?(type_id)
23
+ raise ArgumentError, "Can't build array of type #{@schema_view.type} from iterable"
24
+ end
25
+
26
+ method_name = ARRAY_BUILDER_FROM_ITERABLE_METHOD.fetch(type_id)
27
+ @append_impl = method(method_name)
28
+ end
29
+
30
+ def start_building
31
+ @c_builder.start_appending
32
+ end
33
+
34
+ def append(obj)
35
+ @append_impl.(obj)
36
+ end
37
+
38
+ def finish_building
39
+ @c_builder.finish
40
+ end
41
+
42
+ private
43
+
44
+ def append_bools(obj)
45
+ @c_builder.append_bools(obj)
46
+ end
47
+
48
+ def append_ints(obj)
49
+ @c_builder.append_ints(obj)
50
+ end
51
+
52
+ def append_uints(obj)
53
+ @c_builder.append_uints(obj)
54
+ end
55
+
56
+ def append_doubles(obj)
57
+ @c_builder.append_doubles(obj)
58
+ end
59
+
60
+ def append_strings(obj)
61
+ @c_builder.append_strings(obj)
62
+ end
63
+
64
+ def append_bytes(obj)
65
+ @c_builder.append_bytes(obj)
66
+ end
67
+
68
+ def append_dates(obj)
69
+ @c_builder.append_ints(obj.map { |v| v.nil? ? v : v - EPOCH })
70
+ end
71
+
72
+ def append_timestamps(obj)
73
+ obj =
74
+ case @schema_view.time_unit
75
+ when "s"
76
+ obj.map { |v| v.nil? ? v : v.to_i }
77
+ when "ms"
78
+ # truncates like usec
79
+ obj.map { |v| v.nil? ? v : v.to_i * 1_000 + v.usec / 1_000 }
80
+ when "us"
81
+ obj.map { |v| v.nil? ? v : v.to_i * 1_000_000 + v.usec }
82
+ when "ns"
83
+ obj.map { |v| v.nil? ? v : v.to_i * 1_000_000_000 + v.nsec }
84
+ else
85
+ raise Todo
86
+ end
87
+ @c_builder.append_ints(obj)
88
+ end
89
+
90
+ ARRAY_BUILDER_FROM_ITERABLE_METHOD = {
91
+ Type::BOOL => :append_bools,
92
+ Type::INT8 => :append_ints,
93
+ Type::UINT8 => :append_uints,
94
+ Type::INT16 => :append_ints,
95
+ Type::UINT16 => :append_uints,
96
+ Type::INT32 => :append_ints,
97
+ Type::UINT32 => :append_uints,
98
+ Type::INT64 => :append_ints,
99
+ Type::UINT64 => :append_uints,
100
+ Type::HALF_FLOAT => :append_doubles,
101
+ Type::FLOAT => :append_doubles,
102
+ Type::DOUBLE => :append_doubles,
103
+ Type::STRING => :append_strings,
104
+ Type::LARGE_STRING => :append_strings,
105
+ Type::STRING_VIEW => :append_strings,
106
+ Type::BINARY => :append_bytes,
107
+ Type::LARGE_BINARY => :append_bytes,
108
+ Type::BINARY_VIEW => :append_bytes,
109
+ Type::FIXED_SIZE_BINARY => :append_bytes,
110
+ Type::DATE32 => :append_dates,
111
+ Type::DATE64 => :append_dates,
112
+ Type::TIMESTAMP => :append_timestamps
113
+ }
114
+ end
115
+ end
@@ -0,0 +1,32 @@
1
+ module Nanoarrow
2
+ class ArrayStream
3
+ def initialize(obj, schema = nil)
4
+ @c_array_stream = Utils.c_array_stream(obj, schema)
5
+ end
6
+
7
+ def schema
8
+ Schema.new(@c_array_stream.get_cached_schema)
9
+ end
10
+
11
+ def arrow_c_stream
12
+ @c_array_stream.arrow_c_stream
13
+ end
14
+
15
+ def read_all
16
+ Array.new(@c_array_stream)
17
+ end
18
+
19
+ def read_next
20
+ c_array = @c_array_stream.get_next
21
+ Array.new(CMaterializedArrayStream.from_c_array(c_array)) if c_array
22
+ end
23
+
24
+ def each
25
+ return to_enum(:each) unless block_given?
26
+
27
+ while (c_array = @c_array_stream.get_next)
28
+ yield Array.new(CMaterializedArrayStream.from_c_array(c_array))
29
+ end
30
+ end
31
+ end
32
+ end