require "ffi"
class NDAV
module FFI
TYPE_SIZE_TO_FORMAT = {
1 => "c",
2 => "s",
4 => "l",
8 => "q"
}
module MemoryPointer
module FromNDAV
def from_ndav(array)
from_string(array.to_s)
end
end
module ToNDAV
def to_ndav(format: TYPE_SIZE_TO_FORMAT[type_size], lifetime: self, **)
shape = [size / type_size]
byte_size = shape.reduce(ITEM_SIZES[format], :*)
ptr = ::Fiddle::Pointer.new(address, byte_size)
::NDAV.new(ptr, shape:, format:, lifetime:, **)
end
end
module MemoryViewable
def ndav_descriptor(**)
shape = [size / type_size]
format = TYPE_SIZE_TO_FORMAT[type_size]
item_size = ITEM_SIZES[format]
byte_size = shape.reduce(item_size, :*)
ptr = ::Fiddle::Pointer.new(address, byte_size)
{
data: Fiddle::MemoryView.new(ptr).to_s,
shape:,
strides: ::NDAV.default_strides(shape:, item_size:),
format:,
byte_size:,
readonly?: true
}
end
end
module Converter
def FFIMemoryPointer(array, *, **)
if ::FFI::MemoryPointer === array
array
elsif array.respond_to? :to_ffi_memory_pointer
array.to_ffi_memory_pointer(*, **)
elsif array.respond_to? :to_ndav
array.to_ndav(*, **).to_ffi_memory_pointer
else
::NDAV.new(array, *, **).to_ffi_memory_pointer
end
end
end
end
module Pointer
module FromNDAV
def from_ndav(array)
new(array.item_size, array.to_ptr.to_i)
end
end
module ToNDAV
def to_ndav(shape:, format: TYPE_SIZE_TO_FORMAT[type_size], lifetime: self, **)
byte_size = shape.reduce(ITEM_SIZES[format], :*)
ptr = ::Fiddle::Pointer.new(address, byte_size)
::NDAV.new(ptr, shape:, format:, lifetime:, **)
end
end
module Converter
def FFIPointer(array, *, **)
if array.instance_of? ::FFI::Pointer
array
elsif array.respond_to? :to_ffi_pointer
array.to_ffi_pointer(*, **)
elsif array.respond_to? :to_ndav
array.to_ndav(*, **).to_ffi_pointer
else
::NDAV.new(array, *, **).to_ffi_pointer
end
end
end
end
::NDAV.register ::FFI::MemoryPointer, MemoryPointer, name: :ffi_memory_pointer
::NDAV.register ::FFI::Pointer, Pointer, name: :ffi_pointer
end
end