red-arrow-format 25.0.1 → 26.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/Rakefile +3 -1
- data/lib/arrow-format/array-builder.rb +140 -0
- data/lib/arrow-format/array.rb +541 -22
- data/lib/arrow-format/bitmap-builder.rb +89 -0
- data/lib/arrow-format/bitmap.rb +26 -5
- data/lib/arrow-format/error.rb +1 -0
- data/lib/arrow-format/field.rb +3 -1
- data/lib/arrow-format/record-batch.rb +167 -6
- data/lib/arrow-format/record.rb +60 -0
- data/lib/arrow-format/schema.rb +25 -0
- data/lib/arrow-format/type.rb +284 -89
- data/lib/arrow-format/version.rb +1 -1
- metadata +6 -3
data/lib/arrow-format/array.rb
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
# Licensed to the Apache Software Foundation (ASF) under one
|
|
1
2
|
# or more contributor license agreements. See the NOTICE file
|
|
2
3
|
# distributed with this work for additional information
|
|
3
4
|
# regarding copyright ownership. The ASF licenses this file
|
|
@@ -15,11 +16,24 @@
|
|
|
15
16
|
# under the License.
|
|
16
17
|
|
|
17
18
|
require "bigdecimal"
|
|
19
|
+
require "date"
|
|
18
20
|
|
|
21
|
+
require_relative "array-builder"
|
|
19
22
|
require_relative "bitmap"
|
|
23
|
+
require_relative "bitmap-builder"
|
|
20
24
|
|
|
21
25
|
module ArrowFormat
|
|
26
|
+
using FlatBuffers::AppendAsBytes if FlatBuffers.const_defined?(:AppendAsBytes)
|
|
27
|
+
|
|
22
28
|
class Array
|
|
29
|
+
include Enumerable
|
|
30
|
+
|
|
31
|
+
class << self
|
|
32
|
+
def build(values)
|
|
33
|
+
ArrayBuilder.new(values).build
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
23
37
|
attr_reader :type
|
|
24
38
|
attr_reader :size
|
|
25
39
|
alias_method :length, :size
|
|
@@ -48,6 +62,14 @@ module ArrowFormat
|
|
|
48
62
|
not valid?(i)
|
|
49
63
|
end
|
|
50
64
|
|
|
65
|
+
def [](i)
|
|
66
|
+
if valid?(i)
|
|
67
|
+
unpack_value(i)
|
|
68
|
+
else
|
|
69
|
+
nil
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
|
|
51
73
|
def n_nulls
|
|
52
74
|
if @validity_buffer.nil?
|
|
53
75
|
0
|
|
@@ -60,6 +82,16 @@ module ArrowFormat
|
|
|
60
82
|
@size.zero?
|
|
61
83
|
end
|
|
62
84
|
|
|
85
|
+
def ==(other)
|
|
86
|
+
return false unless other.is_a?(self.class)
|
|
87
|
+
return false unless @size == other.size
|
|
88
|
+
return true if @validity_buffer.nil? and other.validity_buffer.nil?
|
|
89
|
+
if @offset == other.offset and @validity_buffer == other.validity_buffer
|
|
90
|
+
return true
|
|
91
|
+
end
|
|
92
|
+
validity_bitmap == other.validity_bitmap
|
|
93
|
+
end
|
|
94
|
+
|
|
63
95
|
protected
|
|
64
96
|
def slice!(offset, size)
|
|
65
97
|
@offset = offset
|
|
@@ -67,11 +99,11 @@ module ArrowFormat
|
|
|
67
99
|
clear_cache
|
|
68
100
|
end
|
|
69
101
|
|
|
70
|
-
private
|
|
71
102
|
def validity_bitmap
|
|
72
103
|
@validity_bitmap ||= Bitmap.new(@validity_buffer, @offset, @size)
|
|
73
104
|
end
|
|
74
105
|
|
|
106
|
+
private
|
|
75
107
|
def apply_validity(array)
|
|
76
108
|
return array if @validity_buffer.nil?
|
|
77
109
|
validity_bitmap.each_with_index do |is_valid, i|
|
|
@@ -144,6 +176,14 @@ module ArrowFormat
|
|
|
144
176
|
super(NullType.singleton, size, nil)
|
|
145
177
|
end
|
|
146
178
|
|
|
179
|
+
def valid?(i)
|
|
180
|
+
false
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def null?(i)
|
|
184
|
+
true
|
|
185
|
+
end
|
|
186
|
+
|
|
147
187
|
def each_buffer
|
|
148
188
|
return to_enum(__method__) unless block_given?
|
|
149
189
|
end
|
|
@@ -155,10 +195,40 @@ module ArrowFormat
|
|
|
155
195
|
def to_a
|
|
156
196
|
[nil] * @size
|
|
157
197
|
end
|
|
198
|
+
|
|
199
|
+
def each
|
|
200
|
+
return to_enum(__method__) unless block_given?
|
|
201
|
+
|
|
202
|
+
@size.times do
|
|
203
|
+
yield(nil)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
158
206
|
end
|
|
159
207
|
|
|
160
208
|
class PrimitiveArray < Array
|
|
161
|
-
|
|
209
|
+
include BufferAlignable
|
|
210
|
+
|
|
211
|
+
attr_reader :values_buffer
|
|
212
|
+
def initialize(*args)
|
|
213
|
+
n_args = args.size
|
|
214
|
+
if self.class.respond_to?(:type)
|
|
215
|
+
type = self.class.type
|
|
216
|
+
expected_n_args = "1 or 3"
|
|
217
|
+
else
|
|
218
|
+
type = args.shift
|
|
219
|
+
unless type.is_a?(Type)
|
|
220
|
+
type = self.class.type_class.try_convert(type) || type
|
|
221
|
+
end
|
|
222
|
+
expected_n_args = "2 or 4"
|
|
223
|
+
end
|
|
224
|
+
args = build_data(args[0], type) if args.size == 1
|
|
225
|
+
if args.size != 3
|
|
226
|
+
message =
|
|
227
|
+
"wrong number of arguments " +
|
|
228
|
+
"(given #{n_args}, expected #{expected_n_args})"
|
|
229
|
+
raise ArgumentError, message
|
|
230
|
+
end
|
|
231
|
+
size, validity_buffer, values_buffer = args
|
|
162
232
|
super(type, size, validity_buffer)
|
|
163
233
|
@values_buffer = values_buffer
|
|
164
234
|
end
|
|
@@ -170,8 +240,30 @@ module ArrowFormat
|
|
|
170
240
|
apply_validity(@values_buffer.values(@type.buffer_type, offset, @size))
|
|
171
241
|
end
|
|
172
242
|
|
|
243
|
+
def each(&block)
|
|
244
|
+
return to_enum(__method__) {@size} unless block_given?
|
|
245
|
+
|
|
246
|
+
each_value = Enumerator.new(@size) do |yielder|
|
|
247
|
+
offset = element_size * @offset
|
|
248
|
+
@values_buffer.each(@type.buffer_type, offset, @size) do |_, value|
|
|
249
|
+
yielder << value
|
|
250
|
+
end
|
|
251
|
+
end
|
|
252
|
+
if @validity_buffer.nil?
|
|
253
|
+
each_value.each(&block)
|
|
254
|
+
else
|
|
255
|
+
validity_bitmap.zip(each_value) do |is_valid, value|
|
|
256
|
+
if is_valid
|
|
257
|
+
yield(value)
|
|
258
|
+
else
|
|
259
|
+
yield(nil)
|
|
260
|
+
end
|
|
261
|
+
end
|
|
262
|
+
end
|
|
263
|
+
end
|
|
264
|
+
|
|
173
265
|
def each_buffer
|
|
174
|
-
return to_enum(__method__) unless block_given?
|
|
266
|
+
return to_enum(__method__) {2} unless block_given?
|
|
175
267
|
|
|
176
268
|
yield(slice_bitmap_buffer(:validity, @validity_buffer))
|
|
177
269
|
yield(slice_fixed_element_size_buffer(:values,
|
|
@@ -179,43 +271,126 @@ module ArrowFormat
|
|
|
179
271
|
element_size))
|
|
180
272
|
end
|
|
181
273
|
|
|
274
|
+
def ==(other)
|
|
275
|
+
return false unless super(other)
|
|
276
|
+
if @offset == other.offset and @values_buffer == other.values_buffer
|
|
277
|
+
return true
|
|
278
|
+
end
|
|
279
|
+
lazy.zip(other).all? do |value, other_value|
|
|
280
|
+
value == other_value
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
182
284
|
private
|
|
183
285
|
def element_size
|
|
184
286
|
IO::Buffer.size_of(@type.buffer_type)
|
|
185
287
|
end
|
|
288
|
+
|
|
289
|
+
def build_data(data, type)
|
|
290
|
+
n = 0
|
|
291
|
+
validity_buffer_builder = nil
|
|
292
|
+
buffer = +"".b
|
|
293
|
+
pack_template = type.pack_template
|
|
294
|
+
data.each_with_index do |value, i|
|
|
295
|
+
if value.nil?
|
|
296
|
+
validity_buffer_builder ||= SparseBitmapBuilder.new
|
|
297
|
+
validity_buffer_builder.unset(i)
|
|
298
|
+
buffer.append_as_bytes(pack_value(nil, pack_template, type))
|
|
299
|
+
else
|
|
300
|
+
buffer.append_as_bytes(pack_value(value, pack_template, type))
|
|
301
|
+
end
|
|
302
|
+
n += 1
|
|
303
|
+
end
|
|
304
|
+
validity_buffer = validity_buffer_builder&.finish(n)
|
|
305
|
+
pad!(buffer, buffer_padding_size(buffer))
|
|
306
|
+
buffer.freeze
|
|
307
|
+
return n, validity_buffer, IO::Buffer.for(buffer)
|
|
308
|
+
end
|
|
309
|
+
|
|
310
|
+
def pack_value(value, template, type)
|
|
311
|
+
value = 0 if value.nil?
|
|
312
|
+
[value].pack(template)
|
|
313
|
+
end
|
|
314
|
+
|
|
315
|
+
def unpack_value(i)
|
|
316
|
+
offset = element_size * (@offset + i)
|
|
317
|
+
@values_buffer.get_value(@type.buffer_type, offset)
|
|
318
|
+
end
|
|
186
319
|
end
|
|
187
320
|
|
|
188
321
|
class BooleanArray < PrimitiveArray
|
|
189
|
-
|
|
190
|
-
|
|
322
|
+
class << self
|
|
323
|
+
def type
|
|
324
|
+
BooleanType.singleton
|
|
325
|
+
end
|
|
191
326
|
end
|
|
192
327
|
|
|
193
328
|
def to_a
|
|
194
329
|
return [] if empty?
|
|
195
330
|
|
|
196
|
-
|
|
197
|
-
values = @values_bitmap.to_a
|
|
331
|
+
values = values_bitmap.to_a
|
|
198
332
|
apply_validity(values)
|
|
199
333
|
end
|
|
200
334
|
|
|
335
|
+
def each(&block)
|
|
336
|
+
return to_enum(__method__) {@size} unless block_given?
|
|
337
|
+
|
|
338
|
+
if @validity_buffer.nil?
|
|
339
|
+
values_bitmap.each(&block)
|
|
340
|
+
else
|
|
341
|
+
validity_bitmap.zip(values_bitmap) do |is_valid, value|
|
|
342
|
+
if is_valid
|
|
343
|
+
yield(value)
|
|
344
|
+
else
|
|
345
|
+
yield(nil)
|
|
346
|
+
end
|
|
347
|
+
end
|
|
348
|
+
end
|
|
349
|
+
end
|
|
350
|
+
|
|
201
351
|
def each_buffer
|
|
202
|
-
return to_enum(__method__) unless block_given?
|
|
352
|
+
return to_enum(__method__) {2} unless block_given?
|
|
203
353
|
|
|
204
354
|
yield(slice_bitmap_buffer(:validity, @validity_buffer))
|
|
205
355
|
yield(slice_bitmap_buffer(:values, @values_buffer))
|
|
206
356
|
end
|
|
207
357
|
|
|
208
358
|
private
|
|
359
|
+
def values_bitmap
|
|
360
|
+
@values_bitmap ||= Bitmap.new(@values_buffer, @offset, @size)
|
|
361
|
+
end
|
|
362
|
+
|
|
209
363
|
def clear_cache
|
|
210
364
|
super
|
|
211
365
|
@values_bitmap = nil
|
|
212
366
|
end
|
|
367
|
+
|
|
368
|
+
def build_data(data, type)
|
|
369
|
+
n = 0
|
|
370
|
+
validity_buffer_builder = nil
|
|
371
|
+
values_buffer_builder = DenseBitmapBuilder.new
|
|
372
|
+
data.each_with_index do |value, i|
|
|
373
|
+
if value.nil?
|
|
374
|
+
validity_buffer_builder ||= SparseBitmapBuilder.new
|
|
375
|
+
validity_buffer_builder.unset(i)
|
|
376
|
+
values_buffer_builder.append(false)
|
|
377
|
+
elsif value
|
|
378
|
+
values_buffer_builder.append(true)
|
|
379
|
+
else
|
|
380
|
+
values_buffer_builder.append(false)
|
|
381
|
+
end
|
|
382
|
+
n += 1
|
|
383
|
+
end
|
|
384
|
+
validity_buffer = validity_buffer_builder&.finish(n)
|
|
385
|
+
return n, validity_buffer, values_buffer_builder.finish
|
|
386
|
+
end
|
|
387
|
+
|
|
388
|
+
def unpack_value(i)
|
|
389
|
+
values_bitmap[i]
|
|
390
|
+
end
|
|
213
391
|
end
|
|
214
392
|
|
|
215
393
|
class IntArray < PrimitiveArray
|
|
216
|
-
def initialize(size, validity_buffer, values_buffer)
|
|
217
|
-
super(self.class.type, size, validity_buffer, values_buffer)
|
|
218
|
-
end
|
|
219
394
|
end
|
|
220
395
|
|
|
221
396
|
class Int8Array < IntArray
|
|
@@ -283,9 +458,6 @@ module ArrowFormat
|
|
|
283
458
|
end
|
|
284
459
|
|
|
285
460
|
class FloatingPointArray < PrimitiveArray
|
|
286
|
-
def initialize(size, validity_buffer, values_buffer)
|
|
287
|
-
super(self.class.type, size, validity_buffer, values_buffer)
|
|
288
|
-
end
|
|
289
461
|
end
|
|
290
462
|
|
|
291
463
|
class Float32Array < FloatingPointArray
|
|
@@ -308,9 +480,6 @@ module ArrowFormat
|
|
|
308
480
|
end
|
|
309
481
|
|
|
310
482
|
class DateArray < TemporalArray
|
|
311
|
-
def initialize(size, validity_buffer, values_buffer)
|
|
312
|
-
super(self.class.type, size, validity_buffer, values_buffer)
|
|
313
|
-
end
|
|
314
483
|
end
|
|
315
484
|
|
|
316
485
|
class Date32Array < DateArray
|
|
@@ -319,6 +488,18 @@ module ArrowFormat
|
|
|
319
488
|
Date32Type.singleton
|
|
320
489
|
end
|
|
321
490
|
end
|
|
491
|
+
|
|
492
|
+
private
|
|
493
|
+
UNIX_EPOCH = Date.new(1970, 1, 1).jd
|
|
494
|
+
def pack_value(value, template, type)
|
|
495
|
+
if value.nil?
|
|
496
|
+
[0].pack(template)
|
|
497
|
+
elsif value.is_a?(Date)
|
|
498
|
+
[value.jd - UNIX_EPOCH].pack(template)
|
|
499
|
+
else
|
|
500
|
+
[value].pack(template)
|
|
501
|
+
end
|
|
502
|
+
end
|
|
322
503
|
end
|
|
323
504
|
|
|
324
505
|
class Date64Array < DateArray
|
|
@@ -333,21 +514,68 @@ module ArrowFormat
|
|
|
333
514
|
end
|
|
334
515
|
|
|
335
516
|
class Time32Array < TimeArray
|
|
517
|
+
class << self
|
|
518
|
+
def type_class
|
|
519
|
+
Time32Type
|
|
520
|
+
end
|
|
521
|
+
end
|
|
336
522
|
end
|
|
337
523
|
|
|
338
524
|
class Time64Array < TimeArray
|
|
525
|
+
class << self
|
|
526
|
+
def type_class
|
|
527
|
+
Time64Type
|
|
528
|
+
end
|
|
529
|
+
end
|
|
339
530
|
end
|
|
340
531
|
|
|
341
532
|
class TimestampArray < TemporalArray
|
|
533
|
+
class << self
|
|
534
|
+
def type_class
|
|
535
|
+
TimestampType
|
|
536
|
+
end
|
|
537
|
+
end
|
|
538
|
+
|
|
539
|
+
private
|
|
540
|
+
def pack_value(value, template, type)
|
|
541
|
+
if value.nil?
|
|
542
|
+
[0, 0].pack(template)
|
|
543
|
+
elsif value.is_a?(Time)
|
|
544
|
+
case type.unit
|
|
545
|
+
when :second
|
|
546
|
+
value = value.to_i
|
|
547
|
+
when :millisecond
|
|
548
|
+
value = (value.to_i * 1_000) + (value.nsec / 1_000_000)
|
|
549
|
+
when :microsecond
|
|
550
|
+
value = (value.to_i * 1_000_000) + (value.nsec / 1_000)
|
|
551
|
+
when :nanosecond
|
|
552
|
+
value = (value.to_i * 1_000_000_000) + value.nsec
|
|
553
|
+
end
|
|
554
|
+
[value].pack(template)
|
|
555
|
+
else
|
|
556
|
+
[value].pack(template)
|
|
557
|
+
end
|
|
558
|
+
end
|
|
342
559
|
end
|
|
343
560
|
|
|
344
561
|
class IntervalArray < TemporalArray
|
|
345
562
|
end
|
|
346
563
|
|
|
347
564
|
class YearMonthIntervalArray < IntervalArray
|
|
565
|
+
class << self
|
|
566
|
+
def type
|
|
567
|
+
YearMonthIntervalType.singleton
|
|
568
|
+
end
|
|
569
|
+
end
|
|
348
570
|
end
|
|
349
571
|
|
|
350
572
|
class DayTimeIntervalArray < IntervalArray
|
|
573
|
+
class << self
|
|
574
|
+
def type
|
|
575
|
+
DayTimeIntervalType.singleton
|
|
576
|
+
end
|
|
577
|
+
end
|
|
578
|
+
|
|
351
579
|
def to_a
|
|
352
580
|
return [] if empty?
|
|
353
581
|
|
|
@@ -355,19 +583,64 @@ module ArrowFormat
|
|
|
355
583
|
values = @values_buffer.
|
|
356
584
|
each(@type.buffer_type, offset, @size * 2).
|
|
357
585
|
each_slice(2).
|
|
358
|
-
collect do |(_, day), (_,
|
|
359
|
-
[day,
|
|
586
|
+
collect do |(_, day), (_, millisecond)|
|
|
587
|
+
[day, millisecond]
|
|
360
588
|
end
|
|
361
589
|
apply_validity(values)
|
|
362
590
|
end
|
|
363
591
|
|
|
592
|
+
def each(&block)
|
|
593
|
+
return to_enum(__method__) {@size} unless block_given?
|
|
594
|
+
|
|
595
|
+
each_value = Enumerator.new(@size) do |yielder|
|
|
596
|
+
offset = element_size * @offset
|
|
597
|
+
@values_buffer.
|
|
598
|
+
each(@type.buffer_type, offset, @size * 2).
|
|
599
|
+
each_slice(2) do |(_, day), (_, millisecond)|
|
|
600
|
+
yielder << [day, millisecond]
|
|
601
|
+
end
|
|
602
|
+
end
|
|
603
|
+
if @validity_buffer.nil?
|
|
604
|
+
each_value.each(&block)
|
|
605
|
+
else
|
|
606
|
+
validity_bitmap.zip(each_value) do |is_valid, value|
|
|
607
|
+
if is_valid
|
|
608
|
+
yield(value)
|
|
609
|
+
else
|
|
610
|
+
yield(nil)
|
|
611
|
+
end
|
|
612
|
+
end
|
|
613
|
+
end
|
|
614
|
+
end
|
|
615
|
+
|
|
364
616
|
private
|
|
365
617
|
def element_size
|
|
366
618
|
super * 2
|
|
367
619
|
end
|
|
620
|
+
|
|
621
|
+
def pack_value(value, template, type)
|
|
622
|
+
if value.nil?
|
|
623
|
+
[0, 0].pack(template)
|
|
624
|
+
elsif value.is_a?(Hash)
|
|
625
|
+
[value[:day], value[:millisecond]].pack(template)
|
|
626
|
+
else
|
|
627
|
+
value.pack(template)
|
|
628
|
+
end
|
|
629
|
+
end
|
|
630
|
+
|
|
631
|
+
def unpack_value(i)
|
|
632
|
+
offset = element_size * (@offset + i)
|
|
633
|
+
@values_buffer.get_values([@type.buffer_type] * 2, offset)
|
|
634
|
+
end
|
|
368
635
|
end
|
|
369
636
|
|
|
370
637
|
class MonthDayNanoIntervalArray < IntervalArray
|
|
638
|
+
class << self
|
|
639
|
+
def type
|
|
640
|
+
MonthDayNanoIntervalType.singleton
|
|
641
|
+
end
|
|
642
|
+
end
|
|
643
|
+
|
|
371
644
|
def to_a
|
|
372
645
|
return [] if empty?
|
|
373
646
|
|
|
@@ -381,17 +654,75 @@ module ArrowFormat
|
|
|
381
654
|
apply_validity(values)
|
|
382
655
|
end
|
|
383
656
|
|
|
657
|
+
def each(&block)
|
|
658
|
+
return to_enum(__method__) {@size} unless block_given?
|
|
659
|
+
|
|
660
|
+
each_value = Enumerator.new(@size) do |yielder|
|
|
661
|
+
buffer_types = @type.buffer_types
|
|
662
|
+
value_size = IO::Buffer.size_of(buffer_types)
|
|
663
|
+
base_offset = value_size * @offset
|
|
664
|
+
@size.times do |i|
|
|
665
|
+
offset = base_offset + value_size * i
|
|
666
|
+
yielder << @values_buffer.get_values(buffer_types, offset)
|
|
667
|
+
end
|
|
668
|
+
end
|
|
669
|
+
if @validity_buffer.nil?
|
|
670
|
+
each_value.each(&block)
|
|
671
|
+
else
|
|
672
|
+
validity_bitmap.zip(each_value) do |is_valid, value|
|
|
673
|
+
if is_valid
|
|
674
|
+
yield(value)
|
|
675
|
+
else
|
|
676
|
+
yield(nil)
|
|
677
|
+
end
|
|
678
|
+
end
|
|
679
|
+
end
|
|
680
|
+
end
|
|
681
|
+
|
|
384
682
|
private
|
|
385
683
|
def element_size
|
|
386
684
|
IO::Buffer.size_of(@type.buffer_types)
|
|
387
685
|
end
|
|
686
|
+
|
|
687
|
+
def pack_value(value, template, type)
|
|
688
|
+
if value.nil?
|
|
689
|
+
[0, 0, 0].pack(template)
|
|
690
|
+
elsif value.is_a?(Hash)
|
|
691
|
+
[value[:month], value[:day], value[:nanosecond]].pack(template)
|
|
692
|
+
else
|
|
693
|
+
value.pack(template)
|
|
694
|
+
end
|
|
695
|
+
end
|
|
696
|
+
|
|
697
|
+
def unpack_value(i)
|
|
698
|
+
buffer_types = @type.buffer_types
|
|
699
|
+
value_size = IO::Buffer.size_of(buffer_types)
|
|
700
|
+
offset = value_size * (@offset + i)
|
|
701
|
+
@values_buffer.get_values(buffer_types, offset)
|
|
702
|
+
end
|
|
388
703
|
end
|
|
389
704
|
|
|
390
705
|
class DurationArray < TemporalArray
|
|
706
|
+
class << self
|
|
707
|
+
def type_class
|
|
708
|
+
DurationType
|
|
709
|
+
end
|
|
710
|
+
end
|
|
391
711
|
end
|
|
392
712
|
|
|
393
713
|
class VariableSizeBinaryArray < Array
|
|
394
|
-
|
|
714
|
+
include BufferAlignable
|
|
715
|
+
|
|
716
|
+
def initialize(*args)
|
|
717
|
+
if args.size == 1
|
|
718
|
+
args = build_data(args.first)
|
|
719
|
+
elsif args.size != 4
|
|
720
|
+
raise ArgumentError,
|
|
721
|
+
"wrong number of arguments (given #{args.size}, expected 1 or 4)"
|
|
722
|
+
end
|
|
723
|
+
|
|
724
|
+
size, validity_buffer, offsets_buffer, values_buffer = args
|
|
725
|
+
|
|
395
726
|
super(self.class.type, size, validity_buffer)
|
|
396
727
|
@offsets_buffer = offsets_buffer
|
|
397
728
|
@values_buffer = values_buffer
|
|
@@ -431,9 +762,60 @@ module ArrowFormat
|
|
|
431
762
|
end
|
|
432
763
|
|
|
433
764
|
private
|
|
765
|
+
def build_data(data)
|
|
766
|
+
type = self.class.type
|
|
767
|
+
|
|
768
|
+
n = 0
|
|
769
|
+
validity_buffer_builder = nil
|
|
770
|
+
|
|
771
|
+
values = +"".b
|
|
772
|
+
offsets = [0]
|
|
773
|
+
|
|
774
|
+
data.each_with_index do |value, i|
|
|
775
|
+
if value.nil?
|
|
776
|
+
validity_buffer_builder ||= SparseBitmapBuilder.new
|
|
777
|
+
validity_buffer_builder.unset(i)
|
|
778
|
+
|
|
779
|
+
offsets << values.bytesize
|
|
780
|
+
else
|
|
781
|
+
values.append_as_bytes(value)
|
|
782
|
+
offsets << values.bytesize
|
|
783
|
+
end
|
|
784
|
+
|
|
785
|
+
n += 1
|
|
786
|
+
end
|
|
787
|
+
|
|
788
|
+
validity_buffer = validity_buffer_builder&.finish(n)
|
|
789
|
+
|
|
790
|
+
offsets_data = offsets.pack("#{type.offset_pack_template}*")
|
|
791
|
+
pad!(offsets_data, buffer_padding_size(offsets_data))
|
|
792
|
+
offsets_data.freeze
|
|
793
|
+
offsets_buffer = IO::Buffer.for(offsets_data)
|
|
794
|
+
|
|
795
|
+
pad!(values, buffer_padding_size(values))
|
|
796
|
+
values.freeze
|
|
797
|
+
values_buffer = IO::Buffer.for(values)
|
|
798
|
+
|
|
799
|
+
[
|
|
800
|
+
n,
|
|
801
|
+
validity_buffer,
|
|
802
|
+
offsets_buffer,
|
|
803
|
+
values_buffer,
|
|
804
|
+
]
|
|
805
|
+
end
|
|
806
|
+
|
|
434
807
|
def offset_size
|
|
435
808
|
IO::Buffer.size_of(@type.offset_buffer_type)
|
|
436
809
|
end
|
|
810
|
+
|
|
811
|
+
def unpack_value(i)
|
|
812
|
+
offset_types = [@type.offset_buffer_type] * 2
|
|
813
|
+
offsets_offset = offset_size * (@offset + i)
|
|
814
|
+
offset, next_offset = @offsets_buffer.get_values(offset_types,
|
|
815
|
+
offsets_offset)
|
|
816
|
+
length = next_offset - offset
|
|
817
|
+
@values_buffer.get_string(offset, length, @type.encoding)
|
|
818
|
+
end
|
|
437
819
|
end
|
|
438
820
|
|
|
439
821
|
class BinaryArray < VariableSizeBinaryArray
|
|
@@ -472,7 +854,21 @@ module ArrowFormat
|
|
|
472
854
|
end
|
|
473
855
|
|
|
474
856
|
class FixedSizeBinaryArray < Array
|
|
475
|
-
|
|
857
|
+
include BufferAlignable
|
|
858
|
+
|
|
859
|
+
def initialize(type, *args)
|
|
860
|
+
unless type.is_a?(Type)
|
|
861
|
+
type = FixedSizeBinaryType.try_convert(type) || type
|
|
862
|
+
end
|
|
863
|
+
if args.size == 1
|
|
864
|
+
args = build_data(args.first, type)
|
|
865
|
+
elsif args.size != 3
|
|
866
|
+
raise ArgumentError,
|
|
867
|
+
"wrong number of arguments (given #{args.size + 1}, expected 2 or 4)"
|
|
868
|
+
end
|
|
869
|
+
|
|
870
|
+
size, validity_buffer, values_buffer = args
|
|
871
|
+
|
|
476
872
|
super(type, size, validity_buffer)
|
|
477
873
|
@values_buffer = values_buffer
|
|
478
874
|
end
|
|
@@ -495,6 +891,44 @@ module ArrowFormat
|
|
|
495
891
|
end
|
|
496
892
|
apply_validity(values)
|
|
497
893
|
end
|
|
894
|
+
|
|
895
|
+
private
|
|
896
|
+
def build_data(data, type)
|
|
897
|
+
n = 0
|
|
898
|
+
validity_buffer_builder = nil
|
|
899
|
+
|
|
900
|
+
values = +"".b
|
|
901
|
+
byte_width = type.byte_width
|
|
902
|
+
null_value = "\x00" * byte_width
|
|
903
|
+
|
|
904
|
+
data.each_with_index do |value, i|
|
|
905
|
+
if value.nil?
|
|
906
|
+
validity_buffer_builder ||= SparseBitmapBuilder.new
|
|
907
|
+
validity_buffer_builder.unset(i)
|
|
908
|
+
values.append_as_bytes(null_value)
|
|
909
|
+
else
|
|
910
|
+
unless value.bytesize == byte_width
|
|
911
|
+
message = "value size must be #{byte_width}: #{value.inspect}"
|
|
912
|
+
raise ArgumentError, message
|
|
913
|
+
end
|
|
914
|
+
values.append_as_bytes(value)
|
|
915
|
+
end
|
|
916
|
+
|
|
917
|
+
n += 1
|
|
918
|
+
end
|
|
919
|
+
|
|
920
|
+
validity_buffer = validity_buffer_builder&.finish(n)
|
|
921
|
+
|
|
922
|
+
pad!(values, buffer_padding_size(values))
|
|
923
|
+
values.freeze
|
|
924
|
+
values_buffer = IO::Buffer.for(values)
|
|
925
|
+
|
|
926
|
+
[
|
|
927
|
+
n,
|
|
928
|
+
validity_buffer,
|
|
929
|
+
values_buffer,
|
|
930
|
+
]
|
|
931
|
+
end
|
|
498
932
|
end
|
|
499
933
|
|
|
500
934
|
class DecimalArray < FixedSizeBinaryArray
|
|
@@ -605,6 +1039,53 @@ module ArrowFormat
|
|
|
605
1039
|
end
|
|
606
1040
|
|
|
607
1041
|
class ListArray < VariableSizeListArray
|
|
1042
|
+
include BufferAlignable
|
|
1043
|
+
|
|
1044
|
+
def initialize(type, *args)
|
|
1045
|
+
if args.size == 1
|
|
1046
|
+
args = build_data(type, args.first)
|
|
1047
|
+
elsif args.size != 4
|
|
1048
|
+
raise ArgumentError,
|
|
1049
|
+
"wrong number of arguments (given #{args.size + 1}, expected 2 or 5)"
|
|
1050
|
+
end
|
|
1051
|
+
|
|
1052
|
+
super(type, *args)
|
|
1053
|
+
end
|
|
1054
|
+
|
|
1055
|
+
private
|
|
1056
|
+
def build_data(type, data)
|
|
1057
|
+
n = 0
|
|
1058
|
+
validity_buffer_builder = nil
|
|
1059
|
+
|
|
1060
|
+
child_values = []
|
|
1061
|
+
offsets = [0]
|
|
1062
|
+
data.each_with_index do |value, i|
|
|
1063
|
+
if value.nil?
|
|
1064
|
+
validity_buffer_builder ||= SparseBitmapBuilder.new
|
|
1065
|
+
validity_buffer_builder.unset(i)
|
|
1066
|
+
else
|
|
1067
|
+
child_values.concat(value)
|
|
1068
|
+
end
|
|
1069
|
+
offsets << child_values.size
|
|
1070
|
+
n += 1
|
|
1071
|
+
end
|
|
1072
|
+
|
|
1073
|
+
validity_buffer = validity_buffer_builder&.finish(n)
|
|
1074
|
+
|
|
1075
|
+
offsets_data = offsets.pack("#{type.offset_pack_template}*")
|
|
1076
|
+
pad!(offsets_data, buffer_padding_size(offsets_data))
|
|
1077
|
+
offsets_data.freeze
|
|
1078
|
+
offsets_buffer = IO::Buffer.for(offsets_data)
|
|
1079
|
+
|
|
1080
|
+
child = type.child.type.build_array(child_values)
|
|
1081
|
+
|
|
1082
|
+
[
|
|
1083
|
+
n,
|
|
1084
|
+
validity_buffer,
|
|
1085
|
+
offsets_buffer,
|
|
1086
|
+
child,
|
|
1087
|
+
]
|
|
1088
|
+
end
|
|
608
1089
|
end
|
|
609
1090
|
|
|
610
1091
|
class LargeListArray < VariableSizeListArray
|
|
@@ -612,7 +1093,15 @@ module ArrowFormat
|
|
|
612
1093
|
|
|
613
1094
|
class FixedSizeListArray < Array
|
|
614
1095
|
attr_reader :child
|
|
615
|
-
def initialize(type,
|
|
1096
|
+
def initialize(type, *args)
|
|
1097
|
+
if args.size == 1
|
|
1098
|
+
args = build_data(type, args.first)
|
|
1099
|
+
elsif args.size != 3
|
|
1100
|
+
raise ArgumentError,
|
|
1101
|
+
"wrong number of arguments (given #{args.size + 1}, expected 2 or 4)"
|
|
1102
|
+
end
|
|
1103
|
+
|
|
1104
|
+
size, validity_buffer, child = args
|
|
616
1105
|
super(type, size, validity_buffer)
|
|
617
1106
|
@child = child
|
|
618
1107
|
end
|
|
@@ -631,6 +1120,36 @@ module ArrowFormat
|
|
|
631
1120
|
end
|
|
632
1121
|
|
|
633
1122
|
private
|
|
1123
|
+
def build_data(type, data)
|
|
1124
|
+
n = 0
|
|
1125
|
+
validity_buffer_builder = nil
|
|
1126
|
+
|
|
1127
|
+
child_values = []
|
|
1128
|
+
data.each_with_index do |value, i|
|
|
1129
|
+
if value.nil?
|
|
1130
|
+
validity_buffer_builder ||= SparseBitmapBuilder.new
|
|
1131
|
+
validity_buffer_builder.unset(i)
|
|
1132
|
+
child_values.concat([nil] * type.size)
|
|
1133
|
+
else
|
|
1134
|
+
unless value.size == type.size
|
|
1135
|
+
message = "list size must be #{type.size}: #{value.inspect}"
|
|
1136
|
+
raise ArgumentError, message
|
|
1137
|
+
end
|
|
1138
|
+
child_values.concat(value)
|
|
1139
|
+
end
|
|
1140
|
+
n += 1
|
|
1141
|
+
end
|
|
1142
|
+
|
|
1143
|
+
validity_buffer = validity_buffer_builder&.finish(n)
|
|
1144
|
+
child = type.child.type.build_array(child_values)
|
|
1145
|
+
|
|
1146
|
+
[
|
|
1147
|
+
n,
|
|
1148
|
+
validity_buffer,
|
|
1149
|
+
child,
|
|
1150
|
+
]
|
|
1151
|
+
end
|
|
1152
|
+
|
|
634
1153
|
def slice!(offset, size)
|
|
635
1154
|
super
|
|
636
1155
|
@child = @child.slice(@type.size * @offset,
|