Class: Rust::RubyWrapperGenerator

Inherits:
Object
  • Object
show all
Defined in:
lib/rust_require/ruby_wrapper_generator.rb

Overview

This class generates Ruby wrappers for a dylib with information from an info.json file and a ruby Module (or Class) Object

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#rust_lib=(value) ⇒ Object (writeonly)

@rust_lib: path to the rust lib to be included (String)



12
13
14
# File 'lib/rust_require/ruby_wrapper_generator.rb', line 12

def rust_lib=(value)
  @rust_lib = value
end

Instance Method Details

#attach_fns(fn_headers, mod, mod_string) ⇒ Object

attaches fns via FFI to mod



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
# File 'lib/rust_require/ruby_wrapper_generator.rb', line 35

def attach_fns(fn_headers, mod, mod_string)
  # add ffi and the rust lib to mod
  mod.extend FFI::Library
  mod.ffi_lib @rust_lib

  fn_headers.each do |fn|
    rust_fn_name = fn['name']

    # fn mod::fn() => fn _mod_fn_wrapper
    wrapper_name = "_#{mod_string+fn['name']}_wrapper".to_sym

    input_types = fn['inputs'].map { |t| Rust::Types.find_type(t) }
    ffi_input_types = input_types.map { |t| t.ffi_input_type }


    output_type = Rust::Types.find_type(fn['output'])
    ffi_output_type = output_type.ffi_output_type

    # attach fn and define ruby wrapper
    mod.attach_function wrapper_name, ffi_input_types, ffi_output_type
    mod.instance_eval do
      define_method(rust_fn_name) do |*args|
        # check input parameter count
        raise ArgumentError, "wrong number of arguments (#{args.count} for #{input_types.count})" unless args.count == input_types.count

        # check & convert ruby objects before handling them to FFI
        args.map!.with_index do |arg,i|
          input_types[i].ruby_input_conversion(arg)
        end

        # call FFI function and convert output
        raw_output = send wrapper_name, *args
        output_type.ruby_output_conversion raw_output
      end
    end
  end
end

#attach_items(rust_module, mod, mod_string) ⇒ Object

attaches items to mod, mod_string is the mod’s prefix eg ‘mod_submod_’



23
24
25
26
27
28
29
30
31
32
# File 'lib/rust_require/ruby_wrapper_generator.rb', line 23

def attach_items(rust_module, mod, mod_string)
  rust_module['submodules'].each do |x|
    rust_mod = Module.new
    attach_items(x, rust_mod, mod_string+x['name']+'_')
    mod.const_set(x['name'].camelize, rust_mod)
  end

  attach_fns(rust_module['fn_headers'], mod, mod_string)
  attach_structs(rust_module['structs'], mod)
end

#attach_structs(struct_defs, mod) ⇒ Object

attaches structs via FFI to mod



74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/rust_require/ruby_wrapper_generator.rb', line 74

def attach_structs(struct_defs, mod)
  struct_defs.each do |s|
    fields = s['fields'].map do |name, type|
      type = Rust::Types.find_type(type)
      [name.to_sym, type.ffi_output_type]
    end.flatten

    struct = Class.new(FFI::Struct)
    struct.layout *fields

    mod.const_set(s['name'], struct)
  end
end

#include_lib(mod) ⇒ Object

makes items from lib available in mod mod: Module/Class into which the wrappers should get included (Module || Class)



16
17
18
19
# File 'lib/rust_require/ruby_wrapper_generator.rb', line 16

def include_lib(mod)
  # attach items according to @info_file
  attach_items(@info_file, mod, '')
end

#info_file=(info_file) ⇒ Object

@info_file: info.json file, parsed with JSON



7
8
9
# File 'lib/rust_require/ruby_wrapper_generator.rb', line 7

def info_file=(info_file)
  @info_file = info_file
end