Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
2 changed files
with
91 additions
and
239 deletions.
There are no files selected for viewing
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,289 +1,141 @@ | ||
require 'fiddle' | ||
require 'fiddle/import' | ||
require 'ffi' | ||
# require 'ffi/autopointer' | ||
|
||
module FunctionMapping | ||
module Rust | ||
|
||
attr_reader :func_map | ||
module ArrayBackend | ||
extend FFI::Library | ||
|
||
AS_OBJ = :as_obj | ||
ffi_lib File.expand_path('../../libpicky_rust.dylib', __FILE__) # FFI::Library::LIBC | ||
|
||
def __func__ from, external, internal, retval, *params | ||
class_method = external.to_s.match(/\Aself\./) | ||
relative = class_method ? '' : 'self.class.' | ||
params = class_method ? params : params.unshift(Fiddle::TYPE_VOIDP) | ||
# params.map! { |param| param == AS_OBJ ? Fiddle::TYPE_VOIDP : '' } | ||
|
||
func = Fiddle::Function.new( | ||
from[internal.to_s], | ||
params, | ||
retval == AS_OBJ ? Fiddle::TYPE_VOIDP : retval | ||
) | ||
@func_map ||= {} | ||
@func_map[internal] = func | ||
|
||
[func, class_method, relative, retval] | ||
end | ||
attach_function :rust_array_new, [], :pointer | ||
|
||
def __func_impl__ from, external, internal, retval, *params | ||
func, class_method, relative, retval = __func__(from, external, internal, retval, *params) | ||
|
||
# Get the right error position. | ||
begin | ||
/^(.+?):(\d+)/ =~ caller.first | ||
file, line = $1, $2.to_i | ||
rescue | ||
file, line = __FILE__, __LINE__+4 | ||
end | ||
|
||
# Map external interface to C interface. | ||
module_eval(<<-EOS, file, line) | ||
def #{external}(*args, &block) | ||
# p [:calling, :'#{external}', @internal_instance, args] | ||
f = #{relative}func_map[:'#{internal}'] | ||
# p f | ||
#{ | ||
if class_method | ||
# puts "Installing #{relative}#{external}(#{params.join(',')})." | ||
'res = f.call(*args,&block)' | ||
else | ||
# puts "Installing #{external}(#{params.join(',')})." | ||
"res = f.call(@internal_instance,*args,&block)" | ||
end | ||
} | ||
#{ | ||
if retval == AS_OBJ | ||
'res = self.class.from_ptr(res)' | ||
end | ||
} | ||
#{ | ||
# Could it be null? | ||
if retval == Fiddle::TYPE_VOIDP | ||
'if res.null?; res = nil; end' | ||
end | ||
} | ||
res | ||
end | ||
EOS | ||
func | ||
callback :rust_array_sort_by_bang_callback, [:uint16], :uint16 | ||
|
||
attach_function :rust_array_append, [:pointer, :uint16], :pointer | ||
attach_function :rust_array_unshift, [:pointer, :uint16], :pointer | ||
attach_function :rust_array_first, [:pointer], :uint16 | ||
attach_function :rust_array_first_amount, [:pointer, :size_t], :pointer | ||
attach_function :rust_array_last, [:pointer], :uint16 | ||
attach_function :rust_array_plus, [:pointer, :pointer], :pointer | ||
attach_function :rust_array_minus, [:pointer, :pointer], :pointer | ||
attach_function :rust_array_length, [:pointer], :size_t | ||
attach_function :rust_array_intersect, [:pointer, :pointer], :pointer | ||
attach_function :rust_array_slice_bang, [:pointer, :size_t, :size_t], :pointer | ||
attach_function :rust_array_empty, [:pointer], :bool | ||
attach_function :rust_array_eq, [:pointer, :pointer], :bool | ||
attach_function :rust_array_shift, [:pointer], :uint16 | ||
attach_function :rust_array_shift_amount, [:pointer, :size_t], :pointer | ||
attach_function :rust_array_include, [:pointer, :uint16], :bool | ||
attach_function :rust_array_sort_by_bang, [:pointer, :rust_array_sort_by_bang_callback], :pointer | ||
attach_function :rust_array_dup, [:pointer], :pointer | ||
attach_function :rust_array_inspect, [:pointer], :string | ||
end | ||
|
||
end | ||
|
||
module Rust | ||
class Array | ||
extend FunctionMapping | ||
|
||
pr = Fiddle.dlopen File.expand_path('../../libpicky_rust.dylib', __FILE__) | ||
class Array < FFI::AutoPointer | ||
include Rust::ArrayBackend | ||
|
||
attr_reader :internal_instance | ||
|
||
def initialize pointer = nil | ||
@internal_instance = pointer || self.class.new_rust | ||
ObjectSpace.define_finalizer(self, self.class.releaser_for(@internal_instance)) | ||
@internal_instance = pointer || rust_array_new | ||
end | ||
|
||
def self.releaser_for internal_instance | ||
proc { internal_instance.free } | ||
def release | ||
# internal_instance.free # TODO | ||
end | ||
|
||
def self.from_ptr pointer | ||
new(pointer) | ||
end | ||
def to_ptr | ||
@internal_instance | ||
end | ||
|
||
def self.from_ptr pointer | ||
new(pointer) | ||
def << item | ||
# TODO ? | ||
self.class.from_ptr rust_array_append(to_ptr, item) | ||
|
||
# self | ||
end | ||
|
||
def unshift item | ||
self.class.from_ptr rust_array_unshift(to_ptr, item) | ||
end | ||
|
||
# TODO Freeing! | ||
# TODO Add RUBY_OBJECT type which automatically calls its #to_ptr. | ||
# TODO Add RUBY_OBJECT type which automatically calls this class' #from_ptr. | ||
|
||
__func_impl__ pr, :'self.new_rust', :rust_array_new, Fiddle::TYPE_VOIDP | ||
# __func_impl__ pr, :free, :rust_array_free, Fiddle::TYPE_VOIDP | ||
|
||
__func_impl__ pr, :<<, :rust_array_append, FunctionMapping::AS_OBJ, Fiddle::TYPE_SHORT | ||
__func_impl__ pr, :unshift, :rust_array_unshift, FunctionMapping::AS_OBJ, Fiddle::TYPE_SHORT | ||
def first amount = nil | ||
if amount | ||
self.class.from_ptr rust_array_first_amount(to_ptr, amount) | ||
else | ||
rust_array_first(to_ptr) | ||
end | ||
end | ||
def last amount = nil | ||
if amount | ||
self.class.from_ptr rust_array_last_amount(to_ptr, amount) | ||
else | ||
rust_array_last(to_ptr) | ||
end | ||
end | ||
|
||
__func_impl__ pr, :+, :rust_array_plus, FunctionMapping::AS_OBJ, Fiddle::TYPE_VOIDP | ||
__func__ pr, :-, :rust_array_minus, FunctionMapping::AS_OBJ, Fiddle::TYPE_VOIDP | ||
def +(other) | ||
self.class.from_ptr rust_array_plus(to_ptr, other.internal_instance) | ||
end | ||
def -(other) | ||
# TODO dup ? | ||
return self if other.size.zero? | ||
|
||
self.class.from_ptr(self.class.func_map[:rust_array_minus].call(to_ptr, other)) | ||
self.class.from_ptr rust_array_minus(to_ptr, other.internal_instance) | ||
end | ||
|
||
def length | ||
rust_array_length(to_ptr) | ||
end | ||
alias size length | ||
|
||
def intersect other | ||
self.class.from_ptr rust_array_intersect(to_ptr, other.internal_instance) | ||
end | ||
|
||
__func_impl__ pr, :intersect, :rust_array_intersect, FunctionMapping::AS_OBJ, Fiddle::TYPE_VOIDP | ||
__func__ pr, :'slice!', :rust_array_slice_bang, FunctionMapping::AS_OBJ, Fiddle::TYPE_SIZE_T, Fiddle::TYPE_SIZE_T | ||
def slice! start, length # TODO Other ways. | ||
def slice! start, length # TODO Other sigs. | ||
return nil if self.empty? | ||
|
||
pointer = self.class.func_map[:rust_array_slice_bang].call(to_ptr, start, length) | ||
self.class.from_ptr(pointer) | ||
self.class.from_ptr rust_array_slice_bang(to_ptr, start, length) | ||
end | ||
|
||
__func__ pr, :first, :rust_array_first, Fiddle::TYPE_SHORT | ||
__func__ pr, :first, :rust_array_first_amount, Fiddle::TYPE_VOIDP, Fiddle::TYPE_SIZE_T | ||
def empty? | ||
rust_array_empty(to_ptr) | ||
end | ||
|
||
def first(amount = nil) | ||
def shift(amount = nil) | ||
if amount | ||
pointer = self.class.func_map[:rust_array_first_amount].call(to_ptr, amount) | ||
self.class.from_ptr(pointer) | ||
self.class.from_ptr rust_array_shift_amount(to_ptr, amount) | ||
else | ||
self.class.func_map[:rust_array_first].call(to_ptr) | ||
rust_array_shift(to_ptr) | ||
end | ||
end | ||
__func_impl__ pr, :last, :rust_array_last, Fiddle::TYPE_SHORT | ||
|
||
__func_impl__ pr, :length, :rust_array_length, Fiddle::TYPE_SIZE_T | ||
alias size length | ||
def include? item | ||
rust_array_include(to_ptr, item) | ||
end | ||
|
||
__func__ pr, :'sort_by!', :rust_array_sort_by_bang, FunctionMapping::AS_OBJ, Fiddle::TYPE_VOIDP | ||
def sort_by! &block | ||
return self unless block_given? | ||
|
||
cb = Fiddle::Closure::BlockCaller.new(Fiddle::TYPE_INT, [Fiddle::TYPE_INT], &block) | ||
block_func = Fiddle::Function.new(cb, [Fiddle::TYPE_INT], Fiddle::TYPE_INT) | ||
|
||
pointer = self.class.func_map[:rust_array_sort_by_bang].call(to_ptr, block_func) | ||
self.class.from_ptr(pointer) | ||
self.class.from_ptr rust_array_sort_by_bang(to_ptr, block) | ||
end | ||
|
||
__func__ pr, :==, :rust_array_eq, Fiddle::TYPE_CHAR, Fiddle::TYPE_VOIDP | ||
def == other | ||
# return false if other.class | ||
# return false if other.class # TODO | ||
|
||
self.class.func_map[:rust_array_eq].call(to_ptr, other) == 1 | ||
end | ||
|
||
__func__ pr, :empty?, :rust_array_empty, Fiddle::TYPE_CHAR # aka BOOL | ||
def empty? | ||
self.class.func_map[:rust_array_empty].call(to_ptr) == 1 | ||
end | ||
|
||
__func__ pr, :include?, :rust_array_include, Fiddle::TYPE_CHAR, Fiddle::TYPE_VOIDP | ||
def include? item | ||
self.class.func_map[:rust_array_include].call(to_ptr, item) == 1 | ||
rust_array_eq(to_ptr, other.internal_instance) | ||
end | ||
|
||
__func__ pr, :shift, :rust_array_shift, Fiddle::TYPE_SHORT | ||
__func__ pr, :shift, :rust_array_shift_amount, Fiddle::TYPE_VOIDP, Fiddle::TYPE_SIZE_T | ||
|
||
def shift(amount = nil) | ||
if amount | ||
pointer = self.class.func_map[:rust_array_shift_amount].call(to_ptr, amount) | ||
self.class.from_ptr(pointer) | ||
else | ||
self.class.func_map[:rust_array_shift].call(to_ptr) | ||
end | ||
end | ||
|
||
__func__ pr, :dup, :rust_array_dup, Fiddle::TYPE_VOIDP | ||
def dup | ||
self.class.from_ptr(self.class.func_map[:rust_array_dup].call(to_ptr)) | ||
self.class.from_ptr rust_array_dup(to_ptr) | ||
end | ||
|
||
__func__ pr, :inspect, :rust_array_inspect, Fiddle::TYPE_VOIDP | ||
def inspect | ||
self.class.func_map[:rust_array_inspect].call(to_ptr).to_s | ||
rust_array_inspect(to_ptr).to_s | ||
end | ||
end | ||
end | ||
|
||
# require 'ffi' | ||
# | ||
# module Rust | ||
# class ArrayPointer < FFI::AutoPointer | ||
# def self.release(ptr) | ||
# Array.free(ptr) | ||
# end | ||
# | ||
# def append(item) | ||
# Array.append(self, item) | ||
# end | ||
# alias << append | ||
# | ||
# def unshift(item) | ||
# Array.unshift(self, item) | ||
# end | ||
# | ||
# def intersect(other) | ||
# Array.intersect(self, other) | ||
# end | ||
# | ||
# def slice!(offset, amount) | ||
# Array.slice_bang(self, offset, amount) | ||
# end | ||
# | ||
# def first | ||
# Array.first(self) | ||
# end | ||
# | ||
# def last | ||
# Array.last(self) | ||
# end | ||
# | ||
# def length | ||
# Array.length(self) | ||
# end | ||
# alias size length | ||
# end | ||
# class Array | ||
# extend FFI::Library | ||
# ffi_lib 'picky_rust' | ||
# | ||
# attach_function :new, :rust_array_new, [], ArrayPointer | ||
# attach_function :free, :rust_array_free, [ArrayPointer], :void | ||
# | ||
# attach_function :append, :rust_array_append, [ArrayPointer, :uint16], :uint16 | ||
# attach_function :unshift, :rust_array_unshift, [ArrayPointer, :uint16], :uint16 | ||
# | ||
# attach_function :intersect, :rust_array_intersect, [ArrayPointer, ArrayPointer], ArrayPointer | ||
# attach_function :slice_bang, :rust_array_slice_bang, [ArrayPointer, :size_t, :size_t], ArrayPointer | ||
# | ||
# attach_function :first, :rust_array_first, [ArrayPointer], :uint16 | ||
# attach_function :last, :rust_array_last, [ArrayPointer], :uint16 | ||
# | ||
# attach_function :length, :rust_array_length, [ArrayPointer], :size_t | ||
# end | ||
# | ||
# class HashPointer < FFI::AutoPointer | ||
# def self.release(ptr) | ||
# Hash.free(ptr) | ||
# end | ||
# | ||
# # def append_to(key, value) | ||
# # Hash.append_to(self, key, value) | ||
# # end | ||
# | ||
# def set(key, value) | ||
# Hash.set(self, key, value) | ||
# end | ||
# alias []= set | ||
# | ||
# def get(key) | ||
# result = Hash.get(self, key) | ||
# return nil if result.address.zero? | ||
# result | ||
# end | ||
# alias [] get | ||
# | ||
# def length | ||
# Hash.length(self) | ||
# end | ||
# alias size length | ||
# end | ||
# class Hash | ||
# extend FFI::Library | ||
# ffi_lib 'picky_rust' | ||
# | ||
# attach_function :new, :rust_hash_new, [], HashPointer | ||
# attach_function :free, :rust_hash_free, [HashPointer], :void | ||
# | ||
# # Special function. | ||
# # attach_function :append_to, :rust_hash_append_to, [HashPointer, :string, :uint16], :uint16 | ||
# | ||
# attach_function :get, :rust_hash_get, [HashPointer, :string], ArrayPointer | ||
# attach_function :set, :rust_hash_set, [HashPointer, :string, ArrayPointer], ArrayPointer | ||
# | ||
# attach_function :length, :rust_hash_length, [HashPointer], :size_t | ||
# end | ||
# end | ||
end | ||
end |