From a217617454e7d4a3fe38badc627259a62bf6a1d7 Mon Sep 17 00:00:00 2001 From: Yifan Chen <30335308+emecii@users.noreply.github.com> Date: Wed, 9 Sep 2026 05:19:51 -0700 Subject: [PATCH 1/2] GH-51262: [Ruby] Add ListArray values constructor --- .../lib/arrow-format/array.rb | 47 ++++++++++++++++ .../red-arrow-format/lib/arrow-format/type.rb | 4 ++ ruby/red-arrow-format/test/test-list-array.rb | 56 +++++++++++++++++++ 3 files changed, 107 insertions(+) create mode 100644 ruby/red-arrow-format/test/test-list-array.rb diff --git a/ruby/red-arrow-format/lib/arrow-format/array.rb b/ruby/red-arrow-format/lib/arrow-format/array.rb index 20929493e906..ebf8b1ec6849 100644 --- a/ruby/red-arrow-format/lib/arrow-format/array.rb +++ b/ruby/red-arrow-format/lib/arrow-format/array.rb @@ -1037,6 +1037,53 @@ def slice!(offset, size) end class ListArray < VariableSizeListArray + include BufferAlignable + + def initialize(type, *args) + if args.size == 1 + args = build_data(type, args.first) + elsif args.size != 4 + raise ArgumentError, + "wrong number of arguments (given #{args.size + 1}, expected 2 or 5)" + end + + super(type, *args) + end + + private + def build_data(type, data) + n = 0 + validity_buffer_builder = nil + + child_values = [] + offsets = [0] + data.each_with_index do |value, i| + if value.nil? + validity_buffer_builder ||= SparseBitmapBuilder.new + validity_buffer_builder.unset(i) + else + child_values.concat(value) + end + offsets << child_values.size + n += 1 + end + + validity_buffer = validity_buffer_builder&.finish(n) + + offsets_data = offsets.pack("#{type.offset_pack_template}*") + pad!(offsets_data, buffer_padding_size(offsets_data)) + offsets_data.freeze + offsets_buffer = IO::Buffer.for(offsets_data) + + child = type.child.type.build_array(child_values) + + [ + n, + validity_buffer, + offsets_buffer, + child, + ] + end end class LargeListArray < VariableSizeListArray diff --git a/ruby/red-arrow-format/lib/arrow-format/type.rb b/ruby/red-arrow-format/lib/arrow-format/type.rb index 9a6d1f3ed066..432dfdf3f817 100644 --- a/ruby/red-arrow-format/lib/arrow-format/type.rb +++ b/ruby/red-arrow-format/lib/arrow-format/type.rb @@ -1021,6 +1021,10 @@ def offset_buffer_type :s32 # TODO: big endian support end + def offset_pack_template + "l" + end + def build_array(...) ListArray.new(self, ...) end diff --git a/ruby/red-arrow-format/test/test-list-array.rb b/ruby/red-arrow-format/test/test-list-array.rb new file mode 100644 index 000000000000..34dd11867f21 --- /dev/null +++ b/ruby/red-arrow-format/test/test-list-array.rb @@ -0,0 +1,56 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +class TestListArray < Test::Unit::TestCase + def setup + child = ArrowFormat::Field.new("item", ArrowFormat::Int32Type.singleton) + @type = ArrowFormat::ListType.new(child) + end + + sub_test_case("#initialize") do + def test_no_null + values = [[-1, 0], [], [1, 2, 3]] + array = ArrowFormat::ListArray.new(@type, values) + assert_same(@type, array.type) + assert_equal(values, array.to_a) + end + + def test_null_list + values = [[1, 2], nil, [], [3]] + array = ArrowFormat::ListArray.new(@type, values) + assert_equal([0, 2, 2, 2, 3], array.offsets) + assert_equal(1, array.n_nulls) + assert_equal([1, 2, 3], array.child.to_a) + assert_equal(values, array.to_a) + end + + def test_null_child + values = [[1, nil], [], [nil, 2]] + array = ArrowFormat::ListArray.new(@type, values) + assert_equal(2, array.child.n_nulls) + assert_equal([1, nil, nil, 2], array.child.to_a) + assert_equal(values, array.to_a) + end + + def test_empty + array = ArrowFormat::ListArray.new(@type, []) + assert_equal([0], array.offsets) + assert_equal([], array.child.to_a) + assert_equal([], array.to_a) + end + end +end From 665a620534cb38e75c9b4a3244db85e1b307e3d1 Mon Sep 17 00:00:00 2001 From: Yifan Chen Date: Thu, 10 Sep 2026 00:32:22 -0700 Subject: [PATCH 2/2] GH-51262: [Ruby] Remove redundant ListArray null-count assertions Keep the existing value, offset, and child-data assertions as requested in review. Generated-by: OpenAI Codex --- ruby/red-arrow-format/test/test-list-array.rb | 2 -- 1 file changed, 2 deletions(-) diff --git a/ruby/red-arrow-format/test/test-list-array.rb b/ruby/red-arrow-format/test/test-list-array.rb index 34dd11867f21..d3494a09c60c 100644 --- a/ruby/red-arrow-format/test/test-list-array.rb +++ b/ruby/red-arrow-format/test/test-list-array.rb @@ -33,7 +33,6 @@ def test_null_list values = [[1, 2], nil, [], [3]] array = ArrowFormat::ListArray.new(@type, values) assert_equal([0, 2, 2, 2, 3], array.offsets) - assert_equal(1, array.n_nulls) assert_equal([1, 2, 3], array.child.to_a) assert_equal(values, array.to_a) end @@ -41,7 +40,6 @@ def test_null_list def test_null_child values = [[1, nil], [], [nil, 2]] array = ArrowFormat::ListArray.new(@type, values) - assert_equal(2, array.child.n_nulls) assert_equal([1, nil, nil, 2], array.child.to_a) assert_equal(values, array.to_a) end