Class: CrystalRuby::Types::Primitive

Inherits:
Type
  • Object
show all
Defined in:
lib/crystalruby/types/primitive.rb

Constant Summary

Constants inherited from Type

Type::ARC_MUTEX

Constants included from CrystalRuby::Typemaps

CrystalRuby::Typemaps::CRYSTAL_TYPE_MAP, CrystalRuby::Typemaps::C_TYPE_CONVERSIONS, CrystalRuby::Typemaps::C_TYPE_MAP, CrystalRuby::Typemaps::ERROR_VALUE, CrystalRuby::Typemaps::FFI_TYPE_MAP

Instance Attribute Summary

Attributes inherited from Type

#memory, #value

Class Method Summary collapse

Instance Method Summary collapse

Methods inherited from Type

#==, [], anonymous?, base_crystal_class_name, bind_local_vars!, cast!, #coerce, crystal_class_name, crystal_type, crystal_type_to_pointer_type_conversion, #deep_dup, #dup, each_child_address, finalize, fixed_width?, from_ffi_array_repr, inner_type, #inner_value, inspect, #inspect, inspect_name, #item_size, #method_missing, #native, native_type_expr, nested_types, #nil?, numeric?, pointer_to_crystal_type_conversion, primitive?, template_name, type_defn, type_digest, type_expr, union_types, valid?, valid_cast?, validate!, variable_width?, |

Methods included from CrystalRuby::Typemaps

#build_type_map, #convert_crystal_to_lib_type, #convert_lib_to_crystal_type, #crystal_type, #error_value, #ffi_type, #lib_type

Methods included from Allocator

included

Constructor Details

#initialize(rbval) ⇒ Primitive

Primitives just store the Ruby value directly (Or read it from memory if passed a pointer)



6
7
8
9
# File 'lib/crystalruby/types/primitive.rb', line 6

def initialize(rbval)
  super(rbval)
  self.value = rbval.is_a?(FFI::Pointer) ? rbval.send("read_#{ffi_type}") : rbval
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method in the class CrystalRuby::Types::Type

Class Method Details

.build(typename = nil, ffi_type: :uint8, memsize: FFI.type_size(ffi_type), convert_if: [], error: nil, superclass: Primitive, &block) ⇒ Object

Define a new primitive type Primitive types are stored by value and efficiently copied using native FFI types They are written directly into the memory of a container type

(No indirection)


57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
# File 'lib/crystalruby/types/primitive.rb', line 57

def self.build(
  typename = nil,
  ffi_type: :uint8,
  memsize: FFI.type_size(ffi_type),
  convert_if: [],
  error: nil,
  superclass: Primitive,
  &block
)
  Class.new(superclass) do
    %w[typename ffi_type memsize convert_if error].each do |name|
      define_singleton_method(name) { binding.local_variable_get("#{name}") }
      define_method(name) { binding.local_variable_get("#{name}") }
    end

    class_eval(&block) if block_given?

    # Primitives are stored directly in memory as a raw numeric value
    def self.to_ffi_repr(value)
      new(value).inner_value
    end

    def self.refsize
      memsize
    end

    # Primiives are anonymous (Shouldn't be subclassed)
    def self.anonymous?
      true
    end

    def self.copy_to!(rbval, memory:)
      memory.send("write_#{self.ffi_type}", to_ffi_repr(rbval))
    end

    def self.primitive?
      true
    end

    def self.inspect
      inspect_name
    end

    def memory
      @value
    end

    def self.crystal_supertype
      "CrystalRuby::Types::Primitive"
    end
  end
end

.decrement_ref_count!(pointer) ⇒ Object



48
49
50
# File 'lib/crystalruby/types/primitive.rb', line 48

def self.decrement_ref_count!(pointer)
  # Do nothing
end

.fetch_multi(pointer, size, native: false) ⇒ Object

Fetch an array of a given data type from a list pointer (Type can be a byte-array, pointer or numeric type)



40
41
42
43
44
45
46
# File 'lib/crystalruby/types/primitive.rb', line 40

def self.fetch_multi(pointer, size, native: false)
  if numeric?
    pointer.send("get_array_of_#{ffi_type}", 0, size)
  elsif primitive?
    pointer.send("get_array_of_#{ffi_type}", 0, size).map(&method(:from_ffi_array_repr))
  end
end

.fetch_single(pointer, native: false) ⇒ Object

Read a value from a pointer at a given index (Type can be a byte-array, pointer or numeric type)



13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
# File 'lib/crystalruby/types/primitive.rb', line 13

def self.fetch_single(pointer, native: false)
  # Nothing to fetch for Nils
  return if memsize.zero?

  if numeric?
    pointer.send("read_#{ffi_type}")
  elsif primitive?
    single = new(pointer.send("read_#{ffi_type}"))
    if native
      single.value
    else
      single
    end
  end
end

.write_single(pointer, value) ⇒ Object

Write a data type into a pointer at a given index (Type can be a byte-array, pointer or numeric type)



31
32
33
34
35
36
# File 'lib/crystalruby/types/primitive.rb', line 31

def self.write_single(pointer, value)
  # Dont need to write nils
  return if memsize.zero?

  pointer.send("write_#{ffi_type}", to_ffi_repr(value))
end