diff --git a/ruby/red-arrow-format/lib/arrow-format/array.rb b/ruby/red-arrow-format/lib/arrow-format/array.rb index 5bc7588f3a6..951de74475e 100644 --- a/ruby/red-arrow-format/lib/arrow-format/array.rb +++ b/ruby/red-arrow-format/lib/arrow-format/array.rb @@ -480,6 +480,32 @@ class ListArray < VariableSizeListArray class LargeListArray < VariableSizeListArray end + class FixedSizeListArray < Array + attr_reader :child + def initialize(type, size, validity_buffer, child) + super(type, size, validity_buffer) + @child = child + end + + def each_buffer(&block) + return to_enum(__method__) unless block_given? + + yield(slice_bitmap_buffer(:validity, @validity_buffer)) + end + + def to_a + values = @child.to_a.each_slice(@type.size).to_a + apply_validity(values) + end + + private + def slice!(offset, size) + super + @child = @child.slice(@type.size * @offset, + @type.size * (@offset + @size + 1)) + end + end + class StructArray < Array attr_reader :children def initialize(type, size, validity_buffer, children) diff --git a/ruby/red-arrow-format/lib/arrow-format/buffer-alignable.rb b/ruby/red-arrow-format/lib/arrow-format/buffer-alignable.rb index 1ed806d715b..b0cd37cd9a7 100644 --- a/ruby/red-arrow-format/lib/arrow-format/buffer-alignable.rb +++ b/ruby/red-arrow-format/lib/arrow-format/buffer-alignable.rb @@ -15,7 +15,7 @@ # specific language governing permissions and limitations # under the License. -require_relative "flat-buffers" +require_relative "flatbuffers" module ArrowFormat module BufferAlignable diff --git a/ruby/red-arrow-format/lib/arrow-format/flat-buffers.rb b/ruby/red-arrow-format/lib/arrow-format/flatbuffers.rb similarity index 97% rename from ruby/red-arrow-format/lib/arrow-format/flat-buffers.rb rename to ruby/red-arrow-format/lib/arrow-format/flatbuffers.rb index 8b33d8a18e2..913ae9b536d 100644 --- a/ruby/red-arrow-format/lib/arrow-format/flat-buffers.rb +++ b/ruby/red-arrow-format/lib/arrow-format/flatbuffers.rb @@ -25,6 +25,7 @@ require_relative "org/apache/arrow/flatbuf/dictionary_batch" require_relative "org/apache/arrow/flatbuf/duration" require_relative "org/apache/arrow/flatbuf/fixed_size_binary" +require_relative "org/apache/arrow/flatbuf/fixed_size_list" require_relative "org/apache/arrow/flatbuf/floating_point" require_relative "org/apache/arrow/flatbuf/footer" require_relative "org/apache/arrow/flatbuf/int" diff --git a/ruby/red-arrow-format/lib/arrow-format/readable.rb b/ruby/red-arrow-format/lib/arrow-format/readable.rb index b0e65317ad1..c5c1d5d2b3e 100644 --- a/ruby/red-arrow-format/lib/arrow-format/readable.rb +++ b/ruby/red-arrow-format/lib/arrow-format/readable.rb @@ -17,7 +17,7 @@ require_relative "array" require_relative "field" -require_relative "flat-buffers" +require_relative "flatbuffers" require_relative "record-batch" require_relative "schema" require_relative "type" @@ -101,6 +101,9 @@ def read_field(fb_field) type = ListType.new(read_field(fb_field.children[0])) when FB::LargeList type = LargeListType.new(read_field(fb_field.children[0])) + when FB::FixedSizeList + type = FixedSizeListType.new(read_field(fb_field.children[0]), + fb_type.list_size) when FB::Struct children = fb_field.children.collect {|child| read_field(child)} type = StructType.new(children) @@ -223,6 +226,9 @@ def read_column(field, nodes, buffers, body) offsets = body.slice(offsets_buffer.offset, offsets_buffer.length) child = read_column(field.type.child, nodes, buffers, body) field.type.build_array(length, validity, offsets, child) + when FixedSizeListType + child = read_column(field.type.child, nodes, buffers, body) + field.type.build_array(length, validity, child) when StructType children = field.type.children.collect do |child| read_column(child, nodes, buffers, body) diff --git a/ruby/red-arrow-format/lib/arrow-format/type.rb b/ruby/red-arrow-format/lib/arrow-format/type.rb index 3c2d5f3ac9b..fb153450b0f 100644 --- a/ruby/red-arrow-format/lib/arrow-format/type.rb +++ b/ruby/red-arrow-format/lib/arrow-format/type.rb @@ -856,6 +856,34 @@ def to_flatbuffers end end + class FixedSizeListType < Type + attr_reader :child + attr_reader :size + def initialize(child, size) + super() + @child = child + @size = size + end + + def name + "FixedSizeList" + end + + def to_s + "#{super}<#{child.name}: #{child.type}>(#{@size})" + end + + def build_array(size, validity_buffer, child) + FixedSizeListArray.new(self, size, validity_buffer, child) + end + + def to_flatbuffers + fb_type = FB::FixedSizeList::Data.new + fb_type.list_size = @size + fb_type + end + end + class StructType < Type attr_reader :children def initialize(children) diff --git a/ruby/red-arrow-format/test/test-reader.rb b/ruby/red-arrow-format/test/test-reader.rb index 9d54ab987f1..06360f62acd 100644 --- a/ruby/red-arrow-format/test/test-reader.rb +++ b/ruby/red-arrow-format/test/test-reader.rb @@ -561,6 +561,26 @@ def test_large_list [type.to_s, values]) end + def test_fixed_size_list + data_type = Arrow::FixedSizeListDataType.new({ + name: "count", + type: :int8, + }, + 2) + array = Arrow::FixedSizeListArray.new(data_type, + [[-128, 127], nil, [-1, 1]]) + type, values = roundtrip(array) + assert_equal([ + "FixedSizeList(2)", + [ + [-128, 127], + nil, + [-1, 1], + ], + ], + [type.to_s, values]) + end + def test_struct data_type = Arrow::StructDataType.new(count: :int8, visible: :boolean) diff --git a/ruby/red-arrow-format/test/test-writer.rb b/ruby/red-arrow-format/test/test-writer.rb index 629543a58bc..f36a1a252ee 100644 --- a/ruby/red-arrow-format/test/test-writer.rb +++ b/ruby/red-arrow-format/test/test-writer.rb @@ -91,6 +91,9 @@ def convert_type(red_arrow_type) ArrowFormat::ListType.new(convert_field(red_arrow_type.field)) when Arrow::LargeListDataType ArrowFormat::LargeListType.new(convert_field(red_arrow_type.field)) + when Arrow::FixedSizeListDataType + ArrowFormat::FixedSizeListType.new(convert_field(red_arrow_type.field), + red_arrow_type.list_size) when Arrow::StructDataType fields = red_arrow_type.fields.collect do |field| convert_field(field) @@ -161,6 +164,10 @@ def convert_array(red_arrow_array) convert_buffer(red_arrow_array.null_bitmap), convert_buffer(red_arrow_array.value_offsets_buffer), convert_array(red_arrow_array.values_raw)) + when ArrowFormat::FixedSizeListType + type.build_array(red_arrow_array.size, + convert_buffer(red_arrow_array.null_bitmap), + convert_array(red_arrow_array.values_raw)) when ArrowFormat::StructType children = red_arrow_array.fields.collect do |red_arrow_field| convert_array(red_arrow_field) @@ -806,6 +813,22 @@ def test_large_list [type.to_s, values]) end + def test_fixed_size_list + data_type = Arrow::FixedSizeListDataType.new({ + name: "count", + type: :int8, + }, + 2) + array = Arrow::FixedSizeListArray.new(data_type, + [[-128, 127], nil, [-1, 1]]) + type, values = roundtrip(array) + assert_equal([ + "fixed_size_list[2]", + [[-128, 127], nil, [-1, 1]], + ], + [type.to_s, values]) + end + def test_map data_type = Arrow::MapDataType.new(:string, :int8) array = Arrow::MapArray.new(data_type,