red-arrow-format 23.0.1 → 25.0.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 +4 -4
- data/Gemfile +7 -2
- data/Rakefile +23 -1
- data/lib/arrow-format/array.rb +486 -117
- data/lib/arrow-format/bitmap.rb +25 -6
- data/lib/arrow-format/buffer-alignable.rb +35 -0
- data/lib/arrow-format/dictionary.rb +29 -0
- data/lib/arrow-format/error.rb +1 -1
- data/lib/arrow-format/field.rb +24 -3
- data/lib/arrow-format/file-reader.rb +47 -25
- data/lib/arrow-format/file-writer.rb +56 -0
- data/lib/arrow-format/flatbuffers.rb +67 -0
- data/lib/arrow-format/org/apache/arrow/flatbuf/binary.rb +5 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/binary_view.rb +5 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/block.rb +10 -2
- data/lib/arrow-format/org/apache/arrow/flatbuf/body_compression.rb +8 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/body_compression_method.rb +3 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/bool.rb +5 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/buffer.rb +8 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/compression_type.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/date.rb +7 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/date_unit.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/decimal.rb +9 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/dictionary_batch.rb +9 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/dictionary_encoding.rb +11 -2
- data/lib/arrow-format/org/apache/arrow/flatbuf/dictionary_kind.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/duration.rb +7 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/endianness.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/feature.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/field.rb +13 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/field_node.rb +8 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/fixed_size_binary.rb +7 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/fixed_size_list.rb +7 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/floating_point.rb +7 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/footer.rb +22 -2
- data/lib/arrow-format/org/apache/arrow/flatbuf/int.rb +8 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/interval.rb +7 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/interval_unit.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/key_value.rb +8 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/large_binary.rb +5 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/large_list.rb +5 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/large_list_view.rb +5 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/large_utf8.rb +5 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/list.rb +5 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/list_view.rb +5 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/map.rb +8 -2
- data/lib/arrow-format/org/apache/arrow/flatbuf/message.rb +22 -2
- data/lib/arrow-format/org/apache/arrow/flatbuf/message_header.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/metadata_version.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/null.rb +5 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/precision.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/record_batch.rb +12 -2
- data/lib/arrow-format/org/apache/arrow/flatbuf/run_end_encoded.rb +5 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/schema.rb +10 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/sparse_matrix_compressed_axis.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/sparse_matrix_index_csx.rb +12 -2
- data/lib/arrow-format/org/apache/arrow/flatbuf/sparse_tensor.rb +13 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/sparse_tensor_index.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/sparse_tensor_index_coo.rb +13 -4
- data/lib/arrow-format/org/apache/arrow/flatbuf/sparse_tensor_index_csf.rb +14 -4
- data/lib/arrow-format/org/apache/arrow/flatbuf/struct_.rb +5 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/tensor.rb +11 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/tensor_dim.rb +8 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/time.rb +8 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/time_unit.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/timestamp.rb +8 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/type.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/union.rb +8 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/union_mode.rb +1 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/utf8.rb +5 -1
- data/lib/arrow-format/org/apache/arrow/flatbuf/utf8view.rb +5 -1
- data/lib/arrow-format/readable.rb +151 -96
- data/lib/arrow-format/record-batch.rb +70 -1
- data/lib/arrow-format/schema.rb +14 -1
- data/lib/arrow-format/streaming-pull-reader.rb +49 -23
- data/lib/arrow-format/streaming-reader.rb +51 -14
- data/lib/arrow-format/streaming-writer.rb +156 -0
- data/lib/arrow-format/type.rb +397 -34
- data/lib/arrow-format/version.rb +1 -1
- data/lib/arrow-format.rb +2 -0
- data/red-arrow-format.gemspec +2 -1
- metadata +9 -4
data/lib/arrow-format/array.rb
CHANGED
|
@@ -23,35 +23,133 @@ module ArrowFormat
|
|
|
23
23
|
attr_reader :type
|
|
24
24
|
attr_reader :size
|
|
25
25
|
alias_method :length, :size
|
|
26
|
+
attr_reader :offset
|
|
27
|
+
attr_reader :validity_buffer
|
|
26
28
|
def initialize(type, size, validity_buffer)
|
|
27
29
|
@type = type
|
|
28
30
|
@size = size
|
|
31
|
+
@offset = 0
|
|
29
32
|
@validity_buffer = validity_buffer
|
|
33
|
+
@sliced_buffers = {}
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def slice(offset, size=nil)
|
|
37
|
+
sliced = dup
|
|
38
|
+
sliced.slice!(@offset + offset, size || @size - offset)
|
|
39
|
+
sliced
|
|
30
40
|
end
|
|
31
41
|
|
|
32
42
|
def valid?(i)
|
|
33
43
|
return true if @validity_buffer.nil?
|
|
34
|
-
|
|
44
|
+
validity_bitmap[i]
|
|
35
45
|
end
|
|
36
46
|
|
|
37
47
|
def null?(i)
|
|
38
48
|
not valid?(i)
|
|
39
49
|
end
|
|
40
50
|
|
|
51
|
+
def n_nulls
|
|
52
|
+
if @validity_buffer.nil?
|
|
53
|
+
0
|
|
54
|
+
else
|
|
55
|
+
@size - validity_bitmap.popcount
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
def empty?
|
|
60
|
+
@size.zero?
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
protected
|
|
64
|
+
def slice!(offset, size)
|
|
65
|
+
@offset = offset
|
|
66
|
+
@size = size
|
|
67
|
+
clear_cache
|
|
68
|
+
end
|
|
69
|
+
|
|
41
70
|
private
|
|
71
|
+
def validity_bitmap
|
|
72
|
+
@validity_bitmap ||= Bitmap.new(@validity_buffer, @offset, @size)
|
|
73
|
+
end
|
|
74
|
+
|
|
42
75
|
def apply_validity(array)
|
|
43
76
|
return array if @validity_buffer.nil?
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
array[i] = nil if bit.zero?
|
|
77
|
+
validity_bitmap.each_with_index do |is_valid, i|
|
|
78
|
+
array[i] = nil unless is_valid
|
|
47
79
|
end
|
|
48
80
|
array
|
|
49
81
|
end
|
|
82
|
+
|
|
83
|
+
def clear_cache
|
|
84
|
+
@validity_bitmap = nil
|
|
85
|
+
@sliced_buffers = {}
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
def slice_buffer(id, buffer)
|
|
89
|
+
return buffer if buffer.nil?
|
|
90
|
+
return buffer if @offset.zero?
|
|
91
|
+
|
|
92
|
+
@sliced_buffers[id] ||= yield(buffer)
|
|
93
|
+
end
|
|
94
|
+
|
|
95
|
+
def slice_bitmap_buffer(id, buffer)
|
|
96
|
+
slice_buffer(id, buffer) do
|
|
97
|
+
if (@offset % 8).zero?
|
|
98
|
+
buffer.slice(@offset / 8)
|
|
99
|
+
else
|
|
100
|
+
# We need to copy because we can't do bit level slice.
|
|
101
|
+
# TODO: Optimize.
|
|
102
|
+
valid_bytes = []
|
|
103
|
+
Bitmap.new(buffer, @offset, @size).each_slice(8) do |valids|
|
|
104
|
+
valid_byte = 0
|
|
105
|
+
valids.each_with_index do |valid, i|
|
|
106
|
+
valid_byte |= 1 << (i % 8) if valid
|
|
107
|
+
end
|
|
108
|
+
valid_bytes << valid_byte
|
|
109
|
+
end
|
|
110
|
+
IO::Buffer.for(valid_bytes.pack("C*"))
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def slice_fixed_element_size_buffer(id, buffer, element_size)
|
|
116
|
+
slice_buffer(id, buffer) do
|
|
117
|
+
buffer.slice(element_size * @offset)
|
|
118
|
+
end
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def slice_offsets_buffer(id, buffer, buffer_type)
|
|
122
|
+
slice_buffer(id, buffer) do
|
|
123
|
+
offset_size = IO::Buffer.size_of(buffer_type)
|
|
124
|
+
buffer_offset = offset_size * @offset
|
|
125
|
+
first_offset = nil
|
|
126
|
+
# TODO: Optimize
|
|
127
|
+
sliced_buffer = IO::Buffer.new(offset_size * (@size + 1))
|
|
128
|
+
buffer.each(buffer_type,
|
|
129
|
+
buffer_offset,
|
|
130
|
+
@size + 1).with_index do |(_, offset), i|
|
|
131
|
+
first_offset ||= offset
|
|
132
|
+
new_offset = offset - first_offset
|
|
133
|
+
sliced_buffer.set_value(buffer_type,
|
|
134
|
+
offset_size * i,
|
|
135
|
+
new_offset)
|
|
136
|
+
end
|
|
137
|
+
sliced_buffer
|
|
138
|
+
end
|
|
139
|
+
end
|
|
50
140
|
end
|
|
51
141
|
|
|
52
142
|
class NullArray < Array
|
|
53
|
-
def initialize(
|
|
54
|
-
super(
|
|
143
|
+
def initialize(size)
|
|
144
|
+
super(NullType.singleton, size, nil)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def each_buffer
|
|
148
|
+
return to_enum(__method__) unless block_given?
|
|
149
|
+
end
|
|
150
|
+
|
|
151
|
+
def n_nulls
|
|
152
|
+
@size
|
|
55
153
|
end
|
|
56
154
|
|
|
57
155
|
def to_a
|
|
@@ -59,94 +157,175 @@ module ArrowFormat
|
|
|
59
157
|
end
|
|
60
158
|
end
|
|
61
159
|
|
|
62
|
-
class
|
|
160
|
+
class PrimitiveArray < Array
|
|
63
161
|
def initialize(type, size, validity_buffer, values_buffer)
|
|
64
162
|
super(type, size, validity_buffer)
|
|
65
163
|
@values_buffer = values_buffer
|
|
66
164
|
end
|
|
67
165
|
|
|
68
166
|
def to_a
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
167
|
+
return [] if empty?
|
|
168
|
+
|
|
169
|
+
offset = element_size * @offset
|
|
170
|
+
apply_validity(@values_buffer.values(@type.buffer_type, offset, @size))
|
|
171
|
+
end
|
|
172
|
+
|
|
173
|
+
def each_buffer
|
|
174
|
+
return to_enum(__method__) unless block_given?
|
|
175
|
+
|
|
176
|
+
yield(slice_bitmap_buffer(:validity, @validity_buffer))
|
|
177
|
+
yield(slice_fixed_element_size_buffer(:values,
|
|
178
|
+
@values_buffer,
|
|
179
|
+
element_size))
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
private
|
|
183
|
+
def element_size
|
|
184
|
+
IO::Buffer.size_of(@type.buffer_type)
|
|
74
185
|
end
|
|
75
186
|
end
|
|
76
187
|
|
|
77
|
-
class
|
|
78
|
-
def initialize(
|
|
79
|
-
super(
|
|
80
|
-
@values_buffer = values_buffer
|
|
188
|
+
class BooleanArray < PrimitiveArray
|
|
189
|
+
def initialize(size, validity_buffer, values_buffer)
|
|
190
|
+
super(BooleanType.singleton, size, validity_buffer, values_buffer)
|
|
81
191
|
end
|
|
82
192
|
|
|
83
193
|
def to_a
|
|
84
|
-
|
|
194
|
+
return [] if empty?
|
|
195
|
+
|
|
196
|
+
@values_bitmap ||= Bitmap.new(@values_buffer, @offset, @size)
|
|
197
|
+
values = @values_bitmap.to_a
|
|
198
|
+
apply_validity(values)
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def each_buffer
|
|
202
|
+
return to_enum(__method__) unless block_given?
|
|
203
|
+
|
|
204
|
+
yield(slice_bitmap_buffer(:validity, @validity_buffer))
|
|
205
|
+
yield(slice_bitmap_buffer(:values, @values_buffer))
|
|
206
|
+
end
|
|
207
|
+
|
|
208
|
+
private
|
|
209
|
+
def clear_cache
|
|
210
|
+
super
|
|
211
|
+
@values_bitmap = nil
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
class IntArray < PrimitiveArray
|
|
216
|
+
def initialize(size, validity_buffer, values_buffer)
|
|
217
|
+
super(self.class.type, size, validity_buffer, values_buffer)
|
|
85
218
|
end
|
|
86
219
|
end
|
|
87
220
|
|
|
88
221
|
class Int8Array < IntArray
|
|
222
|
+
class << self
|
|
223
|
+
def type
|
|
224
|
+
Int8Type.singleton
|
|
225
|
+
end
|
|
226
|
+
end
|
|
89
227
|
end
|
|
90
228
|
|
|
91
229
|
class UInt8Array < IntArray
|
|
230
|
+
class << self
|
|
231
|
+
def type
|
|
232
|
+
UInt8Type.singleton
|
|
233
|
+
end
|
|
234
|
+
end
|
|
92
235
|
end
|
|
93
236
|
|
|
94
237
|
class Int16Array < IntArray
|
|
238
|
+
class << self
|
|
239
|
+
def type
|
|
240
|
+
Int16Type.singleton
|
|
241
|
+
end
|
|
242
|
+
end
|
|
95
243
|
end
|
|
96
244
|
|
|
97
245
|
class UInt16Array < IntArray
|
|
246
|
+
class << self
|
|
247
|
+
def type
|
|
248
|
+
UInt16Type.singleton
|
|
249
|
+
end
|
|
250
|
+
end
|
|
98
251
|
end
|
|
99
252
|
|
|
100
253
|
class Int32Array < IntArray
|
|
254
|
+
class << self
|
|
255
|
+
def type
|
|
256
|
+
Int32Type.singleton
|
|
257
|
+
end
|
|
258
|
+
end
|
|
101
259
|
end
|
|
102
260
|
|
|
103
261
|
class UInt32Array < IntArray
|
|
262
|
+
class << self
|
|
263
|
+
def type
|
|
264
|
+
UInt32Type.singleton
|
|
265
|
+
end
|
|
266
|
+
end
|
|
104
267
|
end
|
|
105
268
|
|
|
106
269
|
class Int64Array < IntArray
|
|
270
|
+
class << self
|
|
271
|
+
def type
|
|
272
|
+
Int64Type.singleton
|
|
273
|
+
end
|
|
274
|
+
end
|
|
107
275
|
end
|
|
108
276
|
|
|
109
277
|
class UInt64Array < IntArray
|
|
278
|
+
class << self
|
|
279
|
+
def type
|
|
280
|
+
UInt64Type.singleton
|
|
281
|
+
end
|
|
282
|
+
end
|
|
110
283
|
end
|
|
111
284
|
|
|
112
|
-
class FloatingPointArray <
|
|
113
|
-
def initialize(
|
|
114
|
-
super(type, size, validity_buffer)
|
|
115
|
-
@values_buffer = values_buffer
|
|
285
|
+
class FloatingPointArray < PrimitiveArray
|
|
286
|
+
def initialize(size, validity_buffer, values_buffer)
|
|
287
|
+
super(self.class.type, size, validity_buffer, values_buffer)
|
|
116
288
|
end
|
|
117
289
|
end
|
|
118
290
|
|
|
119
291
|
class Float32Array < FloatingPointArray
|
|
120
|
-
|
|
121
|
-
|
|
292
|
+
class << self
|
|
293
|
+
def type
|
|
294
|
+
Float32Type.singleton
|
|
295
|
+
end
|
|
122
296
|
end
|
|
123
297
|
end
|
|
124
298
|
|
|
125
299
|
class Float64Array < FloatingPointArray
|
|
126
|
-
|
|
127
|
-
|
|
300
|
+
class << self
|
|
301
|
+
def type
|
|
302
|
+
Float64Type.singleton
|
|
303
|
+
end
|
|
128
304
|
end
|
|
129
305
|
end
|
|
130
306
|
|
|
131
|
-
class TemporalArray <
|
|
132
|
-
def initialize(type, size, validity_buffer, values_buffer)
|
|
133
|
-
super(type, size, validity_buffer)
|
|
134
|
-
@values_buffer = values_buffer
|
|
135
|
-
end
|
|
307
|
+
class TemporalArray < PrimitiveArray
|
|
136
308
|
end
|
|
137
309
|
|
|
138
310
|
class DateArray < TemporalArray
|
|
311
|
+
def initialize(size, validity_buffer, values_buffer)
|
|
312
|
+
super(self.class.type, size, validity_buffer, values_buffer)
|
|
313
|
+
end
|
|
139
314
|
end
|
|
140
315
|
|
|
141
316
|
class Date32Array < DateArray
|
|
142
|
-
|
|
143
|
-
|
|
317
|
+
class << self
|
|
318
|
+
def type
|
|
319
|
+
Date32Type.singleton
|
|
320
|
+
end
|
|
144
321
|
end
|
|
145
322
|
end
|
|
146
323
|
|
|
147
324
|
class Date64Array < DateArray
|
|
148
|
-
|
|
149
|
-
|
|
325
|
+
class << self
|
|
326
|
+
def type
|
|
327
|
+
Date64Type.singleton
|
|
328
|
+
end
|
|
150
329
|
end
|
|
151
330
|
end
|
|
152
331
|
|
|
@@ -154,122 +333,141 @@ module ArrowFormat
|
|
|
154
333
|
end
|
|
155
334
|
|
|
156
335
|
class Time32Array < TimeArray
|
|
157
|
-
def to_a
|
|
158
|
-
apply_validity(@values_buffer.values(:s32, 0, @size))
|
|
159
|
-
end
|
|
160
336
|
end
|
|
161
337
|
|
|
162
338
|
class Time64Array < TimeArray
|
|
163
|
-
def to_a
|
|
164
|
-
apply_validity(@values_buffer.values(:s64, 0, @size))
|
|
165
|
-
end
|
|
166
339
|
end
|
|
167
340
|
|
|
168
341
|
class TimestampArray < TemporalArray
|
|
169
|
-
def to_a
|
|
170
|
-
apply_validity(@values_buffer.values(:s64, 0, @size))
|
|
171
|
-
end
|
|
172
342
|
end
|
|
173
343
|
|
|
174
344
|
class IntervalArray < TemporalArray
|
|
175
345
|
end
|
|
176
346
|
|
|
177
347
|
class YearMonthIntervalArray < IntervalArray
|
|
178
|
-
def to_a
|
|
179
|
-
apply_validity(@values_buffer.values(:s32, 0, @size))
|
|
180
|
-
end
|
|
181
348
|
end
|
|
182
349
|
|
|
183
350
|
class DayTimeIntervalArray < IntervalArray
|
|
184
351
|
def to_a
|
|
352
|
+
return [] if empty?
|
|
353
|
+
|
|
354
|
+
offset = element_size * @offset
|
|
185
355
|
values = @values_buffer.
|
|
186
|
-
each(
|
|
356
|
+
each(@type.buffer_type, offset, @size * 2).
|
|
187
357
|
each_slice(2).
|
|
188
358
|
collect do |(_, day), (_, time)|
|
|
189
359
|
[day, time]
|
|
190
360
|
end
|
|
191
361
|
apply_validity(values)
|
|
192
362
|
end
|
|
363
|
+
|
|
364
|
+
private
|
|
365
|
+
def element_size
|
|
366
|
+
super * 2
|
|
367
|
+
end
|
|
193
368
|
end
|
|
194
369
|
|
|
195
370
|
class MonthDayNanoIntervalArray < IntervalArray
|
|
196
371
|
def to_a
|
|
197
|
-
|
|
372
|
+
return [] if empty?
|
|
373
|
+
|
|
374
|
+
buffer_types = @type.buffer_types
|
|
198
375
|
value_size = IO::Buffer.size_of(buffer_types)
|
|
376
|
+
base_offset = value_size * @offset
|
|
199
377
|
values = @size.times.collect do |i|
|
|
200
|
-
offset = value_size * i
|
|
378
|
+
offset = base_offset + value_size * i
|
|
201
379
|
@values_buffer.get_values(buffer_types, offset)
|
|
202
380
|
end
|
|
203
381
|
apply_validity(values)
|
|
204
382
|
end
|
|
383
|
+
|
|
384
|
+
private
|
|
385
|
+
def element_size
|
|
386
|
+
IO::Buffer.size_of(@type.buffer_types)
|
|
387
|
+
end
|
|
205
388
|
end
|
|
206
389
|
|
|
207
390
|
class DurationArray < TemporalArray
|
|
208
|
-
def to_a
|
|
209
|
-
apply_validity(@values_buffer.values(:s64, 0, @size))
|
|
210
|
-
end
|
|
211
391
|
end
|
|
212
392
|
|
|
213
|
-
class
|
|
214
|
-
def initialize(
|
|
215
|
-
super(type, size, validity_buffer)
|
|
393
|
+
class VariableSizeBinaryArray < Array
|
|
394
|
+
def initialize(size, validity_buffer, offsets_buffer, values_buffer)
|
|
395
|
+
super(self.class.type, size, validity_buffer)
|
|
216
396
|
@offsets_buffer = offsets_buffer
|
|
217
397
|
@values_buffer = values_buffer
|
|
218
398
|
end
|
|
219
399
|
|
|
220
|
-
def
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
400
|
+
def each_buffer
|
|
401
|
+
return to_enum(__method__) unless block_given?
|
|
402
|
+
|
|
403
|
+
yield(slice_bitmap_buffer(:validity, @validity_buffer))
|
|
404
|
+
yield(slice_offsets_buffer(:offsets,
|
|
405
|
+
@offsets_buffer,
|
|
406
|
+
@type.offset_buffer_type))
|
|
407
|
+
sliced_values_buffer = slice_buffer(:values, @values_buffer) do
|
|
408
|
+
first_offset = @offsets_buffer.get_value(@type.offset_buffer_type,
|
|
409
|
+
offset_size * @offset)
|
|
410
|
+
@values_buffer.slice(first_offset)
|
|
227
411
|
end
|
|
228
|
-
|
|
412
|
+
yield(sliced_values_buffer)
|
|
229
413
|
end
|
|
230
|
-
end
|
|
231
414
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
415
|
+
def offsets
|
|
416
|
+
return [0] if empty?
|
|
417
|
+
|
|
418
|
+
@offsets_buffer.
|
|
419
|
+
each(@type.offset_buffer_type, offset_size * @offset, @size + 1).
|
|
420
|
+
collect {|_, offset| offset}
|
|
236
421
|
end
|
|
237
422
|
|
|
238
|
-
def
|
|
239
|
-
|
|
423
|
+
def to_a
|
|
424
|
+
return [] if empty?
|
|
425
|
+
|
|
426
|
+
values = offsets.each_cons(2).collect do |offset, next_offset|
|
|
427
|
+
length = next_offset - offset
|
|
428
|
+
@values_buffer.get_string(offset, length, @type.encoding)
|
|
429
|
+
end
|
|
430
|
+
apply_validity(values)
|
|
240
431
|
end
|
|
241
|
-
end
|
|
242
432
|
|
|
243
|
-
class LargeBinaryArray < VariableSizeBinaryLayoutArray
|
|
244
433
|
private
|
|
245
|
-
def
|
|
246
|
-
|
|
434
|
+
def offset_size
|
|
435
|
+
IO::Buffer.size_of(@type.offset_buffer_type)
|
|
247
436
|
end
|
|
437
|
+
end
|
|
248
438
|
|
|
249
|
-
|
|
250
|
-
|
|
439
|
+
class BinaryArray < VariableSizeBinaryArray
|
|
440
|
+
class << self
|
|
441
|
+
def type
|
|
442
|
+
BinaryType.singleton
|
|
443
|
+
end
|
|
251
444
|
end
|
|
252
445
|
end
|
|
253
446
|
|
|
254
|
-
class
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
447
|
+
class LargeBinaryArray < VariableSizeBinaryArray
|
|
448
|
+
class << self
|
|
449
|
+
def type
|
|
450
|
+
LargeBinaryType.singleton
|
|
451
|
+
end
|
|
258
452
|
end
|
|
453
|
+
end
|
|
259
454
|
|
|
260
|
-
|
|
261
|
-
Encoding::UTF_8
|
|
262
|
-
end
|
|
455
|
+
class VariableSizeUTF8Array < VariableSizeBinaryArray
|
|
263
456
|
end
|
|
264
457
|
|
|
265
|
-
class
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
458
|
+
class UTF8Array < VariableSizeUTF8Array
|
|
459
|
+
class << self
|
|
460
|
+
def type
|
|
461
|
+
UTF8Type.singleton
|
|
462
|
+
end
|
|
269
463
|
end
|
|
464
|
+
end
|
|
270
465
|
|
|
271
|
-
|
|
272
|
-
|
|
466
|
+
class LargeUTF8Array < VariableSizeUTF8Array
|
|
467
|
+
class << self
|
|
468
|
+
def type
|
|
469
|
+
LargeUTF8Type.singleton
|
|
470
|
+
end
|
|
273
471
|
end
|
|
274
472
|
end
|
|
275
473
|
|
|
@@ -279,7 +477,18 @@ module ArrowFormat
|
|
|
279
477
|
@values_buffer = values_buffer
|
|
280
478
|
end
|
|
281
479
|
|
|
480
|
+
def each_buffer
|
|
481
|
+
return to_enum(__method__) unless block_given?
|
|
482
|
+
|
|
483
|
+
yield(slice_bitmap_buffer(:validity, @validity_buffer))
|
|
484
|
+
yield(slice_fixed_element_size_buffer(:values,
|
|
485
|
+
@values_buffer,
|
|
486
|
+
@type.byte_width))
|
|
487
|
+
end
|
|
488
|
+
|
|
282
489
|
def to_a
|
|
490
|
+
return [] if empty?
|
|
491
|
+
|
|
283
492
|
byte_width = @type.byte_width
|
|
284
493
|
values = 0.step(@size * byte_width - 1, byte_width).collect do |offset|
|
|
285
494
|
@values_buffer.get_string(offset, byte_width)
|
|
@@ -290,10 +499,13 @@ module ArrowFormat
|
|
|
290
499
|
|
|
291
500
|
class DecimalArray < FixedSizeBinaryArray
|
|
292
501
|
def to_a
|
|
502
|
+
return [] if empty?
|
|
503
|
+
|
|
293
504
|
byte_width = @type.byte_width
|
|
294
505
|
buffer_types = [:u64] * (byte_width / 8 - 1) + [:s64]
|
|
506
|
+
base_offset = byte_width * @offset
|
|
295
507
|
values = 0.step(@size * byte_width - 1, byte_width).collect do |offset|
|
|
296
|
-
@values_buffer.get_values(buffer_types, offset)
|
|
508
|
+
@values_buffer.get_values(buffer_types, base_offset + offset)
|
|
297
509
|
end
|
|
298
510
|
apply_validity(values).collect do |value|
|
|
299
511
|
if value.nil?
|
|
@@ -319,8 +531,8 @@ module ArrowFormat
|
|
|
319
531
|
elsif @type.scale > 0
|
|
320
532
|
n_digits = string.bytesize
|
|
321
533
|
n_digits -= 1 if value < 0
|
|
322
|
-
if n_digits
|
|
323
|
-
prefix = "0." + ("0" * (@type.scale - n_digits
|
|
534
|
+
if n_digits <= @type.scale
|
|
535
|
+
prefix = "0." + ("0" * (@type.scale - n_digits))
|
|
324
536
|
if value < 0
|
|
325
537
|
string[1, 0] = prefix
|
|
326
538
|
else
|
|
@@ -341,45 +553,107 @@ module ArrowFormat
|
|
|
341
553
|
end
|
|
342
554
|
|
|
343
555
|
class VariableSizeListArray < Array
|
|
556
|
+
attr_reader :child
|
|
344
557
|
def initialize(type, size, validity_buffer, offsets_buffer, child)
|
|
345
558
|
super(type, size, validity_buffer)
|
|
346
559
|
@offsets_buffer = offsets_buffer
|
|
347
560
|
@child = child
|
|
348
561
|
end
|
|
349
562
|
|
|
563
|
+
def each_buffer(&block)
|
|
564
|
+
return to_enum(__method__) unless block_given?
|
|
565
|
+
|
|
566
|
+
yield(slice_bitmap_buffer(:validity, @validity_buffer))
|
|
567
|
+
yield(slice_offsets_buffer(:offsets,
|
|
568
|
+
@offsets_buffer,
|
|
569
|
+
@type.offset_buffer_type))
|
|
570
|
+
end
|
|
571
|
+
|
|
572
|
+
def offsets
|
|
573
|
+
return [0] if empty?
|
|
574
|
+
|
|
575
|
+
@offsets_buffer.
|
|
576
|
+
each(@type.offset_buffer_type, offset_size * @offset, @size + 1).
|
|
577
|
+
collect {|_, offset| offset}
|
|
578
|
+
end
|
|
579
|
+
|
|
350
580
|
def to_a
|
|
581
|
+
return [] if empty?
|
|
582
|
+
|
|
351
583
|
child_values = @child.to_a
|
|
352
|
-
values =
|
|
353
|
-
each(offset_type, 0, @size + 1).
|
|
354
|
-
each_cons(2).
|
|
355
|
-
collect do |(_, offset), (_, next_offset)|
|
|
584
|
+
values = offsets.each_cons(2).collect do |offset, next_offset|
|
|
356
585
|
child_values[offset...next_offset]
|
|
357
586
|
end
|
|
358
587
|
apply_validity(values)
|
|
359
588
|
end
|
|
360
|
-
end
|
|
361
589
|
|
|
362
|
-
class ListArray < VariableSizeListArray
|
|
363
590
|
private
|
|
364
|
-
def
|
|
365
|
-
|
|
591
|
+
def offset_size
|
|
592
|
+
IO::Buffer.size_of(@type.offset_buffer_type)
|
|
593
|
+
end
|
|
594
|
+
|
|
595
|
+
def slice!(offset, size)
|
|
596
|
+
super
|
|
597
|
+
first_offset =
|
|
598
|
+
@offsets_buffer.get_value(@type.offset_buffer_type,
|
|
599
|
+
offset_size * @offset)
|
|
600
|
+
last_offset =
|
|
601
|
+
@offsets_buffer.get_value(@type.offset_buffer_type,
|
|
602
|
+
offset_size * (@offset + @size + 1))
|
|
603
|
+
@child = @child.slice(first_offset, last_offset - first_offset)
|
|
366
604
|
end
|
|
367
605
|
end
|
|
368
606
|
|
|
607
|
+
class ListArray < VariableSizeListArray
|
|
608
|
+
end
|
|
609
|
+
|
|
369
610
|
class LargeListArray < VariableSizeListArray
|
|
611
|
+
end
|
|
612
|
+
|
|
613
|
+
class FixedSizeListArray < Array
|
|
614
|
+
attr_reader :child
|
|
615
|
+
def initialize(type, size, validity_buffer, child)
|
|
616
|
+
super(type, size, validity_buffer)
|
|
617
|
+
@child = child
|
|
618
|
+
end
|
|
619
|
+
|
|
620
|
+
def each_buffer(&block)
|
|
621
|
+
return to_enum(__method__) unless block_given?
|
|
622
|
+
|
|
623
|
+
yield(slice_bitmap_buffer(:validity, @validity_buffer))
|
|
624
|
+
end
|
|
625
|
+
|
|
626
|
+
def to_a
|
|
627
|
+
return [] if empty?
|
|
628
|
+
|
|
629
|
+
values = @child.to_a.each_slice(@type.size).to_a
|
|
630
|
+
apply_validity(values)
|
|
631
|
+
end
|
|
632
|
+
|
|
370
633
|
private
|
|
371
|
-
def
|
|
372
|
-
|
|
634
|
+
def slice!(offset, size)
|
|
635
|
+
super
|
|
636
|
+
@child = @child.slice(@type.size * @offset,
|
|
637
|
+
@type.size * (@offset + @size + 1))
|
|
373
638
|
end
|
|
374
639
|
end
|
|
375
640
|
|
|
376
641
|
class StructArray < Array
|
|
642
|
+
attr_reader :children
|
|
377
643
|
def initialize(type, size, validity_buffer, children)
|
|
378
644
|
super(type, size, validity_buffer)
|
|
379
645
|
@children = children
|
|
380
646
|
end
|
|
381
647
|
|
|
648
|
+
def each_buffer(&block)
|
|
649
|
+
return to_enum(__method__) unless block_given?
|
|
650
|
+
|
|
651
|
+
yield(slice_bitmap_buffer(:validity, @validity_buffer))
|
|
652
|
+
end
|
|
653
|
+
|
|
382
654
|
def to_a
|
|
655
|
+
return [] if empty?
|
|
656
|
+
|
|
383
657
|
if @children.empty?
|
|
384
658
|
values = [[]] * @size
|
|
385
659
|
else
|
|
@@ -388,10 +662,20 @@ module ArrowFormat
|
|
|
388
662
|
end
|
|
389
663
|
apply_validity(values)
|
|
390
664
|
end
|
|
665
|
+
|
|
666
|
+
private
|
|
667
|
+
def slice!(offset, size)
|
|
668
|
+
super
|
|
669
|
+
@children = @children.collect do |child|
|
|
670
|
+
child.slice(offset, size)
|
|
671
|
+
end
|
|
672
|
+
end
|
|
391
673
|
end
|
|
392
674
|
|
|
393
675
|
class MapArray < VariableSizeListArray
|
|
394
676
|
def to_a
|
|
677
|
+
return [] if empty?
|
|
678
|
+
|
|
395
679
|
super.collect do |entries|
|
|
396
680
|
if entries.nil?
|
|
397
681
|
entries
|
|
@@ -404,19 +688,37 @@ module ArrowFormat
|
|
|
404
688
|
end
|
|
405
689
|
end
|
|
406
690
|
end
|
|
407
|
-
|
|
408
|
-
private
|
|
409
|
-
def offset_type
|
|
410
|
-
:s32 # TODO: big endian support
|
|
411
|
-
end
|
|
412
691
|
end
|
|
413
692
|
|
|
414
693
|
class UnionArray < Array
|
|
694
|
+
attr_reader :types_buffer
|
|
695
|
+
attr_reader :children
|
|
415
696
|
def initialize(type, size, types_buffer, children)
|
|
416
697
|
super(type, size, nil)
|
|
417
698
|
@types_buffer = types_buffer
|
|
418
699
|
@children = children
|
|
419
700
|
end
|
|
701
|
+
|
|
702
|
+
def each_type(&block)
|
|
703
|
+
return [].each(&block) if empty?
|
|
704
|
+
|
|
705
|
+
return to_enum(__method__) unless block_given?
|
|
706
|
+
|
|
707
|
+
@types_buffer.each(type_buffer_type,
|
|
708
|
+
type_element_size * @offset,
|
|
709
|
+
@size) do |_, type|
|
|
710
|
+
yield(type)
|
|
711
|
+
end
|
|
712
|
+
end
|
|
713
|
+
|
|
714
|
+
private
|
|
715
|
+
def type_buffer_type
|
|
716
|
+
:S8
|
|
717
|
+
end
|
|
718
|
+
|
|
719
|
+
def type_element_size
|
|
720
|
+
IO::Buffer.size_of(type_buffer_type)
|
|
721
|
+
end
|
|
420
722
|
end
|
|
421
723
|
|
|
422
724
|
class DenseUnionArray < UnionArray
|
|
@@ -429,41 +731,108 @@ module ArrowFormat
|
|
|
429
731
|
@offsets_buffer = offsets_buffer
|
|
430
732
|
end
|
|
431
733
|
|
|
734
|
+
def each_buffer(&block)
|
|
735
|
+
return to_enum(__method__) unless block_given?
|
|
736
|
+
|
|
737
|
+
# TODO: Dictionary delta support (slice support)
|
|
738
|
+
yield(@types_buffer)
|
|
739
|
+
yield(@offsets_buffer)
|
|
740
|
+
end
|
|
741
|
+
|
|
742
|
+
def each_offset(&block)
|
|
743
|
+
return [].each(&block) if empty?
|
|
744
|
+
|
|
745
|
+
return to_enum(__method__) unless block_given?
|
|
746
|
+
|
|
747
|
+
@offsets_buffer.each(@type.offset_buffer_type,
|
|
748
|
+
offset_element_size * @offset,
|
|
749
|
+
@size) do |_, offset|
|
|
750
|
+
yield(offset)
|
|
751
|
+
end
|
|
752
|
+
end
|
|
753
|
+
|
|
432
754
|
def to_a
|
|
755
|
+
return [] if empty?
|
|
756
|
+
|
|
433
757
|
children_values = @children.collect(&:to_a)
|
|
434
|
-
|
|
435
|
-
offsets = @offsets_buffer.each(:s32, 0, @size)
|
|
436
|
-
types.zip(offsets).collect do |(_, type), (_, offset)|
|
|
758
|
+
each_type.zip(each_offset).collect do |type, offset|
|
|
437
759
|
index = @type.resolve_type_index(type)
|
|
438
760
|
children_values[index][offset]
|
|
439
761
|
end
|
|
440
762
|
end
|
|
763
|
+
|
|
764
|
+
private
|
|
765
|
+
def offset_buffer_type
|
|
766
|
+
:s32
|
|
767
|
+
end
|
|
768
|
+
|
|
769
|
+
def offset_element_size
|
|
770
|
+
IO::Buffer.size_of(offset_buffer_type)
|
|
771
|
+
end
|
|
441
772
|
end
|
|
442
773
|
|
|
443
774
|
class SparseUnionArray < UnionArray
|
|
775
|
+
def each_buffer(&block)
|
|
776
|
+
return to_enum(__method__) unless block_given?
|
|
777
|
+
|
|
778
|
+
yield(slice_fixed_element_size_buffer(:types,
|
|
779
|
+
@types_buffer,
|
|
780
|
+
type_element_size))
|
|
781
|
+
end
|
|
782
|
+
|
|
444
783
|
def to_a
|
|
784
|
+
return [] if empty?
|
|
785
|
+
|
|
445
786
|
children_values = @children.collect(&:to_a)
|
|
446
|
-
|
|
787
|
+
each_type.with_index.collect do |type, i|
|
|
447
788
|
index = @type.resolve_type_index(type)
|
|
448
789
|
children_values[index][i]
|
|
449
790
|
end
|
|
450
791
|
end
|
|
792
|
+
|
|
793
|
+
private
|
|
794
|
+
def slice!(offset, size)
|
|
795
|
+
super
|
|
796
|
+
@children = @children.collect do |child|
|
|
797
|
+
child.slice(offset, size)
|
|
798
|
+
end
|
|
799
|
+
end
|
|
451
800
|
end
|
|
452
801
|
|
|
453
802
|
class DictionaryArray < Array
|
|
454
|
-
|
|
803
|
+
attr_reader :indices_buffer
|
|
804
|
+
attr_reader :dictionaries
|
|
805
|
+
def initialize(type,
|
|
806
|
+
size,
|
|
807
|
+
validity_buffer,
|
|
808
|
+
indices_buffer,
|
|
809
|
+
dictionaries)
|
|
455
810
|
super(type, size, validity_buffer)
|
|
456
811
|
@indices_buffer = indices_buffer
|
|
457
|
-
@
|
|
812
|
+
@dictionaries = dictionaries
|
|
813
|
+
end
|
|
814
|
+
|
|
815
|
+
# TODO: Slice support
|
|
816
|
+
def each_buffer
|
|
817
|
+
return to_enum(__method__) unless block_given?
|
|
818
|
+
|
|
819
|
+
yield(@validity_buffer)
|
|
820
|
+
yield(@indices_buffer)
|
|
821
|
+
end
|
|
822
|
+
|
|
823
|
+
def indices
|
|
824
|
+
buffer_type = @type.index_type.buffer_type
|
|
825
|
+
offset = IO::Buffer.size_of(buffer_type) * @offset
|
|
826
|
+
apply_validity(@indices_buffer.values(buffer_type, offset, @size))
|
|
458
827
|
end
|
|
459
828
|
|
|
460
829
|
def to_a
|
|
830
|
+
return [] if empty?
|
|
831
|
+
|
|
461
832
|
values = []
|
|
462
|
-
@
|
|
463
|
-
values.concat(
|
|
833
|
+
@dictionaries.each do |dictionary|
|
|
834
|
+
values.concat(dictionary.array.to_a)
|
|
464
835
|
end
|
|
465
|
-
buffer_type = @type.index_type.buffer_type
|
|
466
|
-
indices = apply_validity(@indices_buffer.values(buffer_type, 0, @size))
|
|
467
836
|
indices.collect do |index|
|
|
468
837
|
if index.nil?
|
|
469
838
|
nil
|