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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +3 -0
- data/LICENSE.txt +208 -0
- data/NOTICE.txt +5 -0
- data/README.md +54 -0
- data/ext/nanoarrow/array.c +99 -0
- data/ext/nanoarrow/array_builder.c +268 -0
- data/ext/nanoarrow/array_stream.c +201 -0
- data/ext/nanoarrow/array_view.c +177 -0
- data/ext/nanoarrow/buffer.c +46 -0
- data/ext/nanoarrow/capsule.c +89 -0
- data/ext/nanoarrow/ext.c +23 -0
- data/ext/nanoarrow/ext.h +89 -0
- data/ext/nanoarrow/extconf.rb +7 -0
- data/ext/nanoarrow/mat_array_stream.c +186 -0
- data/ext/nanoarrow/nanoarrow/nanoarrow.h +4482 -0
- data/ext/nanoarrow/nanoarrow.c +4117 -0
- data/ext/nanoarrow/rc.c +34 -0
- data/ext/nanoarrow/schema.c +346 -0
- data/ext/nanoarrow/schema_builder.c +251 -0
- data/ext/nanoarrow/schema_view.c +204 -0
- data/ext/nanoarrow/types.c +48 -0
- data/ext/nanoarrow/utils.c +202 -0
- data/lib/nanoarrow/array.rb +97 -0
- data/lib/nanoarrow/array_builder.rb +115 -0
- data/lib/nanoarrow/array_stream.rb +32 -0
- data/lib/nanoarrow/iterator.rb +113 -0
- data/lib/nanoarrow/schema.rb +85 -0
- data/lib/nanoarrow/types.rb +157 -0
- data/lib/nanoarrow/utils.rb +127 -0
- data/lib/nanoarrow/version.rb +3 -0
- data/lib/nanoarrow.rb +28 -0
- metadata +70 -0
|
@@ -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
|