Skip to content

Commit da499a5

Browse files
committed
GH-50439 Add ArrowFormat::{,Large}{Binary,UTF8}Array.new(values)
Signed-off-by: Aaditya Srinivasan <aadityasri03@gmail.com>
1 parent 98a92c2 commit da499a5

6 files changed

Lines changed: 289 additions & 1 deletion

File tree

ruby/red-arrow-format/lib/arrow-format/array.rb

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -537,7 +537,17 @@ class DurationArray < TemporalArray
537537
end
538538

539539
class VariableSizeBinaryArray < Array
540-
def initialize(size, validity_buffer, offsets_buffer, values_buffer)
540+
include BufferAlignable
541+
def initialize(*args)
542+
if args.size == 1
543+
args = build_data(args.first)
544+
elsif args.size != 4
545+
raise ArgumentError,
546+
"wrong number of arguments (given #{args.size}, expected 1 or 4)"
547+
end
548+
549+
size, validity_buffer, offsets_buffer, values_buffer = args
550+
541551
super(self.class.type, size, validity_buffer)
542552
@offsets_buffer = offsets_buffer
543553
@values_buffer = values_buffer
@@ -577,6 +587,48 @@ def to_a
577587
end
578588

579589
private
590+
def build_data(data)
591+
type = self.class.type
592+
593+
n = 0
594+
validity_buffer_builder = nil
595+
596+
values = +"".b
597+
offsets = [0]
598+
599+
data.each_with_index do |value, i|
600+
if value.nil?
601+
validity_buffer_builder ||= SparseBitmapBuilder.new
602+
validity_buffer_builder.unset(i)
603+
604+
offsets << values.bytesize
605+
else
606+
values.append_as_bytes(value)
607+
offsets << values.bytesize
608+
end
609+
610+
n += 1
611+
end
612+
613+
validity_buffer = validity_buffer_builder&.finish(n)
614+
615+
pad!(values, buffer_padding_size(values))
616+
values.freeze
617+
offsets_data = offsets.pack("#{type.offset_pack_template}*")
618+
pad!(offsets_data, buffer_padding_size(offsets_data))
619+
offsets_data.freeze
620+
offsets_buffer = IO::Buffer.for(offsets_data)
621+
622+
values_buffer = IO::Buffer.for(values)
623+
624+
[
625+
n,
626+
validity_buffer,
627+
offsets_buffer,
628+
values_buffer,
629+
]
630+
end
631+
580632
def offset_size
581633
IO::Buffer.size_of(@type.offset_buffer_type)
582634
end

ruby/red-arrow-format/lib/arrow-format/type.rb

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -715,6 +715,10 @@ def build_array(...)
715715
def to_flatbuffers
716716
FB::Binary::Data.new
717717
end
718+
719+
def offset_pack_template
720+
"l<"
721+
end
718722
end
719723

720724
class LargeBinaryType < VariableSizeBinaryType
@@ -743,6 +747,10 @@ def build_array(...)
743747
def to_flatbuffers
744748
FB::LargeBinary::Data.new
745749
end
750+
751+
def offset_pack_template
752+
"q<"
753+
end
746754
end
747755

748756
class UTF8Type < VariableSizeBinaryType
@@ -771,6 +779,10 @@ def build_array(...)
771779
def to_flatbuffers
772780
FB::Utf8::Data.new
773781
end
782+
783+
def offset_pack_template
784+
"l<"
785+
end
774786
end
775787

776788
class LargeUTF8Type < VariableSizeBinaryType
@@ -799,6 +811,10 @@ def build_array(...)
799811
def to_flatbuffers
800812
FB::LargeUtf8::Data.new
801813
end
814+
815+
def offset_pack_template
816+
"q<"
817+
end
802818
end
803819

804820
class FixedSizeBinaryType < Type
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
class TestBinaryArray < Test::Unit::TestCase
19+
sub_test_case("#initialize") do
20+
def test_no_null
21+
values = ["\x00\x01".b, "\xff\x10".b]
22+
assert_equal(values,
23+
ArrowFormat::BinaryArray.new(values).to_a)
24+
end
25+
26+
def test_mixed
27+
values = ["\x00\x01".b, nil, "\xff\x10".b]
28+
assert_equal(values,
29+
ArrowFormat::BinaryArray.new(values).to_a)
30+
end
31+
end
32+
33+
sub_test_case("#==") do
34+
def test_no_slice
35+
values = ["\x00\x01".b, nil, "\xff\x10".b]
36+
array1 = ArrowFormat::BinaryArray.new(values)
37+
array2 = ArrowFormat::BinaryArray.new(values)
38+
assert_equal(array1, array2)
39+
end
40+
41+
def test_sliced
42+
values = ["\x00\x01".b, nil, "\xff\x10".b]
43+
array1 = ArrowFormat::BinaryArray.new(values)
44+
array2 = ArrowFormat::BinaryArray.new(["".b, *values, "".b])
45+
assert_equal(array1, array2.slice(1, 3))
46+
end
47+
48+
def test_sliced_different_content
49+
values = ["\x00\x01".b, nil, "\xff\x10".b]
50+
array1 = ArrowFormat::BinaryArray.new(values)
51+
array2 = ArrowFormat::BinaryArray.new(["".b, "".b, *values, "".b])
52+
assert_not_equal(array1, array2.slice(1, 3))
53+
end
54+
end
55+
end
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
class TestLargeBinaryArray < Test::Unit::TestCase
19+
sub_test_case("#initialize") do
20+
def test_no_null
21+
values = ["\x00\x01".b, "\xff\x10".b]
22+
assert_equal(values,
23+
ArrowFormat::LargeBinaryArray.new(values).to_a)
24+
end
25+
26+
def test_mixed
27+
values = ["\x00\x01".b, nil, "\xff\x10".b]
28+
assert_equal(values,
29+
ArrowFormat::LargeBinaryArray.new(values).to_a)
30+
end
31+
end
32+
33+
sub_test_case("#==") do
34+
def test_no_slice
35+
values = ["\x00\x01".b, nil, "\xff\x10".b]
36+
array1 = ArrowFormat::LargeBinaryArray.new(values)
37+
array2 = ArrowFormat::LargeBinaryArray.new(values)
38+
assert_equal(array1, array2)
39+
end
40+
41+
def test_sliced
42+
values = ["\x00\x01".b, nil, "\xff\x10".b]
43+
array1 = ArrowFormat::LargeBinaryArray.new(values)
44+
array2 = ArrowFormat::LargeBinaryArray.new(["".b, *values, "".b])
45+
assert_equal(array1, array2.slice(1, 3))
46+
end
47+
48+
def test_sliced_different_content
49+
values = ["\x00\x01".b, nil, "\xff\x10".b]
50+
array1 = ArrowFormat::LargeBinaryArray.new(values)
51+
array2 = ArrowFormat::LargeBinaryArray.new(["".b, "".b, *values, "".b])
52+
assert_not_equal(array1, array2.slice(1, 3))
53+
end
54+
end
55+
end
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
class TestLargeUTF8Array < Test::Unit::TestCase
19+
sub_test_case("#initialize") do
20+
def test_no_null
21+
values = ["Hello", "World"]
22+
assert_equal(values,
23+
ArrowFormat::LargeUTF8Array.new(values).to_a)
24+
end
25+
26+
def test_mixed
27+
values = ["Hello", nil, "World"]
28+
assert_equal(values,
29+
ArrowFormat::LargeUTF8Array.new(values).to_a)
30+
end
31+
end
32+
33+
sub_test_case("#==") do
34+
def test_no_slice
35+
values = ["Hello", nil, "World"]
36+
array1 = ArrowFormat::LargeUTF8Array.new(values)
37+
array2 = ArrowFormat::LargeUTF8Array.new(values)
38+
assert_equal(array1, array2)
39+
end
40+
41+
def test_sliced
42+
values = ["Hello", nil, "World"]
43+
array1 = ArrowFormat::LargeUTF8Array.new(values)
44+
array2 = ArrowFormat::LargeUTF8Array.new(["", *values, ""])
45+
assert_equal(array1, array2.slice(1, 3))
46+
end
47+
48+
def test_sliced_different_content
49+
values = ["Hello", nil, "World"]
50+
array1 = ArrowFormat::LargeUTF8Array.new(values)
51+
array2 = ArrowFormat::LargeUTF8Array.new(["", "", *values, ""])
52+
assert_not_equal(array1, array2.slice(1, 3))
53+
end
54+
end
55+
end
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# Licensed to the Apache Software Foundation (ASF) under one
2+
# or more contributor license agreements. See the NOTICE file
3+
# distributed with this work for additional information
4+
# regarding copyright ownership. The ASF licenses this file
5+
# to you under the Apache License, Version 2.0 (the
6+
# "License"); you may not use this file except in compliance
7+
# with the License. You may obtain a copy of the License at
8+
#
9+
# http://www.apache.org/licenses/LICENSE-2.0
10+
#
11+
# Unless required by applicable law or agreed to in writing,
12+
# software distributed under the License is distributed on an
13+
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
14+
# KIND, either express or implied. See the License for the
15+
# specific language governing permissions and limitations
16+
# under the License.
17+
18+
class TestUTF8Array < Test::Unit::TestCase
19+
sub_test_case("#initialize") do
20+
def test_no_null
21+
values = ["Hello", "World"]
22+
assert_equal(values,
23+
ArrowFormat::UTF8Array.new(values).to_a)
24+
end
25+
26+
def test_mixed
27+
values = ["Hello", nil, "World"]
28+
assert_equal(values,
29+
ArrowFormat::UTF8Array.new(values).to_a)
30+
end
31+
end
32+
33+
sub_test_case("#==") do
34+
def test_no_slice
35+
values = ["Hello", nil, "World"]
36+
array1 = ArrowFormat::UTF8Array.new(values)
37+
array2 = ArrowFormat::UTF8Array.new(values)
38+
assert_equal(array1, array2)
39+
end
40+
41+
def test_sliced
42+
values = ["Hello", nil, "World"]
43+
array1 = ArrowFormat::UTF8Array.new(values)
44+
array2 = ArrowFormat::UTF8Array.new(["", *values, ""])
45+
assert_equal(array1, array2.slice(1, 3))
46+
end
47+
48+
def test_sliced_different_content
49+
values = ["Hello", nil, "World"]
50+
array1 = ArrowFormat::UTF8Array.new(values)
51+
array2 = ArrowFormat::UTF8Array.new(["", "", *values, ""])
52+
assert_not_equal(array1, array2.slice(1, 3))
53+
end
54+
end
55+
end

0 commit comments

Comments
 (0)