Skip to content

Commit

Permalink
Move to FFI.
Browse files Browse the repository at this point in the history
  • Loading branch information
floere committed Oct 18, 2015
1 parent e3f4517 commit c8fa9f2
Show file tree
Hide file tree
Showing 2 changed files with 91 additions and 239 deletions.
Binary file modified indexes/lib/picky-indexes/libpicky_rust.dylib
Binary file not shown.
330 changes: 91 additions & 239 deletions indexes/lib/picky-indexes/rust/array.rb
@@ -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

0 comments on commit c8fa9f2

Please sign in to comment.