Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
67 changes: 46 additions & 21 deletions ruby/red-arrow-format/lib/arrow-format/array.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@
require_relative "bitmap-builder"

module ArrowFormat
using FlatBuffers::AppendAsBytes if FlatBuffers.const_defined?(:AppendAsBytes)

class Array
attr_reader :type
attr_reader :size
Expand Down Expand Up @@ -160,7 +162,25 @@ def to_a
end

class PrimitiveArray < Array
def initialize(type, size, validity_buffer, values_buffer)
include BufferAlignable

def initialize(*args)
n_args = args.size
if self.class.respond_to?(:type)
type = self.class.type
expected_n_args = "1 or 3"
else
type = args.shift
expected_n_args = "2 or 4"
end
args = build_data(args[0], type) if args.size == 1
if args.size != 3
message =
"wrong number of arguments " +
"(given #{n_args}, expected #{expected_n_args})"
raise ArgumentError, message
end
size, validity_buffer, values_buffer = args
super(type, size, validity_buffer)
@values_buffer = values_buffer
end
Expand All @@ -185,20 +205,34 @@ def each_buffer
def element_size
IO::Buffer.size_of(@type.buffer_type)
end

def build_data(data, type)
n = 0
validity_buffer_builder = nil
buffer = +"".b
pack_template = type.pack_template
data.each_with_index do |value, i|
if value.nil?
validity_buffer_builder ||= SparseBitmapBuilder.new
validity_buffer_builder.unset(i)
buffer.append_as_bytes([0].pack(pack_template))
else
buffer.append_as_bytes([value].pack(pack_template))
end
n += 1
end
validity_buffer = validity_buffer_builder&.finish(n)
pad!(buffer, buffer_padding_size(buffer))
buffer.freeze
return n, validity_buffer, IO::Buffer.for(buffer)
end
end

class BooleanArray < PrimitiveArray
def initialize(*args)
if args.size == 1
args = build_data(args[0])
end
n_args = args.size
if args.size != 3
message = "wrong number of arguments (given #{n_args}, expected 1 or 3)"
raise ArgumentError, message
class << self
def type
BooleanType.singleton
end
size, validity_buffer, values_buffer = args
super(BooleanType.singleton, size, validity_buffer, values_buffer)
end

def to_a
Expand All @@ -222,7 +256,7 @@ def clear_cache
@values_bitmap = nil
end

def build_data(data)
def build_data(data, type)
n = 0
validity_buffer_builder = nil
values_buffer_builder = DenseBitmapBuilder.new
Expand All @@ -244,9 +278,6 @@ def build_data(data)
end

class IntArray < PrimitiveArray
def initialize(size, validity_buffer, values_buffer)
super(self.class.type, size, validity_buffer, values_buffer)
end
end

class Int8Array < IntArray
Expand Down Expand Up @@ -314,9 +345,6 @@ def type
end

class FloatingPointArray < PrimitiveArray
def initialize(size, validity_buffer, values_buffer)
super(self.class.type, size, validity_buffer, values_buffer)
end
end

class Float32Array < FloatingPointArray
Expand All @@ -339,9 +367,6 @@ class TemporalArray < PrimitiveArray
end

class DateArray < TemporalArray
def initialize(size, validity_buffer, values_buffer)
super(self.class.type, size, validity_buffer, values_buffer)
end
end

class Date32Array < DateArray
Expand Down
5 changes: 3 additions & 2 deletions ruby/red-arrow-format/lib/arrow-format/bitmap-builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@
require_relative "buffer-alignable"

module ArrowFormat
using FlatBuffers::AppendAsBytes if FlatBuffers.const_defined?(:AppendAsBytes)

class DenseBitmapBuilder
include BufferAlignable

Expand All @@ -36,8 +38,7 @@ def append(value)

def finish
flush if @n_bits > 0
padding_size = buffer_padding_size(@buffer)
@buffer.append_as_bytes(padding(padding_size)) if padding_size > 0
pad!(@buffer, buffer_padding_size(@buffer))
@buffer.freeze
IO::Buffer.for(@buffer)
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -207,7 +207,7 @@ def read_schema
def read_bitmap(bitmap)
builder = DenseBitmapBuilder.new
bitmap.each do |bit|
builder.append(bit == 1 ? true : false)
builder.append(bit == 1)
end
builder.finish
end
Expand Down Expand Up @@ -248,8 +248,6 @@ def read_hex_value(value)

def read_values(data, type)
case type
when BooleanType
read_bitmap(data.collect {|boolean| boolean ? 1 : 0})
when DayTimeIntervalType
buffer_types = [type.buffer_type] * 2
size = IO::Buffer.size_of(buffer_types)
Expand Down Expand Up @@ -314,14 +312,37 @@ def read_values(data, type)
end
end

def apply_validity(values, validity)
values.zip(validity).collect do |value, valid|
if valid == 1
value
else
nil
end
end
end

def read_array(column, type)
length = column["count"]
case type
when NullType
type.build_array(length)
when BooleanType,
NumberType,
TemporalType,
when BooleanType
values = apply_validity(column["DATA"], column["VALIDITY"])
type.build_array(values)
when NumberType
values = column["DATA"].collect do |value|
if value.is_a?(String)
# If the type is 64bit such as `Int64Type`, `value` is a
# string not integer to round-trip data through JSON.
Integer(value, 10)
else
value
end
end
values = apply_validity(values, column["VALIDITY"])
type.build_array(values)
when TemporalType,
FixedSizeBinaryType
validity_buffer = read_bitmap(column["VALIDITY"])
values_buffer = read_values(column["DATA"], type)
Expand Down
Loading
Loading