crystalruby 0.2.3 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2 -0
- data/README.md +389 -193
- data/Rakefile +4 -3
- data/crystalruby.gemspec +2 -2
- data/exe/crystalruby +1 -0
- data/lib/crystalruby/adapter.rb +131 -65
- data/lib/crystalruby/arc_mutex.rb +47 -0
- data/lib/crystalruby/compilation.rb +32 -3
- data/lib/crystalruby/config.rb +41 -37
- data/lib/crystalruby/function.rb +211 -68
- data/lib/crystalruby/library.rb +153 -48
- data/lib/crystalruby/reactor.rb +40 -23
- data/lib/crystalruby/source_reader.rb +86 -0
- data/lib/crystalruby/template.rb +16 -5
- data/lib/crystalruby/templates/function.cr +11 -10
- data/lib/crystalruby/templates/index.cr +53 -66
- data/lib/crystalruby/templates/inline_chunk.cr +1 -1
- data/lib/crystalruby/templates/ruby_interface.cr +34 -0
- data/lib/crystalruby/templates/top_level_function.cr +62 -0
- data/lib/crystalruby/templates/top_level_ruby_interface.cr +33 -0
- data/lib/crystalruby/typebuilder.rb +11 -55
- data/lib/crystalruby/typemaps.rb +92 -67
- data/lib/crystalruby/types/concerns/allocator.rb +80 -0
- data/lib/crystalruby/types/fixed_width/named_tuple.cr +80 -0
- data/lib/crystalruby/types/fixed_width/named_tuple.rb +86 -0
- data/lib/crystalruby/types/fixed_width/proc.cr +45 -0
- data/lib/crystalruby/types/fixed_width/proc.rb +79 -0
- data/lib/crystalruby/types/fixed_width/tagged_union.cr +53 -0
- data/lib/crystalruby/types/fixed_width/tagged_union.rb +109 -0
- data/lib/crystalruby/types/fixed_width/tuple.cr +82 -0
- data/lib/crystalruby/types/fixed_width/tuple.rb +92 -0
- data/lib/crystalruby/types/fixed_width.cr +138 -0
- data/lib/crystalruby/types/fixed_width.rb +205 -0
- data/lib/crystalruby/types/primitive.cr +21 -0
- data/lib/crystalruby/types/primitive.rb +117 -0
- data/lib/crystalruby/types/primitive_types/bool.cr +34 -0
- data/lib/crystalruby/types/primitive_types/bool.rb +11 -0
- data/lib/crystalruby/types/primitive_types/nil.cr +35 -0
- data/lib/crystalruby/types/primitive_types/nil.rb +16 -0
- data/lib/crystalruby/types/primitive_types/numbers.cr +37 -0
- data/lib/crystalruby/types/primitive_types/numbers.rb +28 -0
- data/lib/crystalruby/types/primitive_types/symbol.cr +55 -0
- data/lib/crystalruby/types/primitive_types/symbol.rb +35 -0
- data/lib/crystalruby/types/primitive_types/time.cr +35 -0
- data/lib/crystalruby/types/primitive_types/time.rb +25 -0
- data/lib/crystalruby/types/type.cr +64 -0
- data/lib/crystalruby/types/type.rb +239 -30
- data/lib/crystalruby/types/variable_width/array.cr +74 -0
- data/lib/crystalruby/types/variable_width/array.rb +88 -0
- data/lib/crystalruby/types/variable_width/hash.cr +146 -0
- data/lib/crystalruby/types/variable_width/hash.rb +117 -0
- data/lib/crystalruby/types/variable_width/string.cr +36 -0
- data/lib/crystalruby/types/variable_width/string.rb +18 -0
- data/lib/crystalruby/types/variable_width.cr +23 -0
- data/lib/crystalruby/types/variable_width.rb +46 -0
- data/lib/crystalruby/types.rb +32 -13
- data/lib/crystalruby/version.rb +2 -2
- data/lib/crystalruby.rb +13 -6
- metadata +41 -19
- data/lib/crystalruby/types/array.rb +0 -15
- data/lib/crystalruby/types/bool.rb +0 -3
- data/lib/crystalruby/types/hash.rb +0 -17
- data/lib/crystalruby/types/named_tuple.rb +0 -28
- data/lib/crystalruby/types/nil.rb +0 -3
- data/lib/crystalruby/types/numbers.rb +0 -5
- data/lib/crystalruby/types/string.rb +0 -3
- data/lib/crystalruby/types/symbol.rb +0 -3
- data/lib/crystalruby/types/time.rb +0 -8
- data/lib/crystalruby/types/tuple.rb +0 -17
- data/lib/crystalruby/types/type_serializer/json.rb +0 -41
- data/lib/crystalruby/types/type_serializer.rb +0 -37
- data/lib/crystalruby/types/typedef.rb +0 -57
- data/lib/crystalruby/types/union_type.rb +0 -43
- data/lib/module.rb +0 -3
@@ -0,0 +1,117 @@
|
|
1
|
+
module CrystalRuby
|
2
|
+
module Types
|
3
|
+
class Primitive < Type
|
4
|
+
# Primitives just store the Ruby value directly
|
5
|
+
# (Or read it from memory if passed a pointer)
|
6
|
+
def initialize(rbval)
|
7
|
+
super(rbval)
|
8
|
+
self.value = rbval.is_a?(FFI::Pointer) ? rbval.send("read_#{ffi_type}") : rbval
|
9
|
+
end
|
10
|
+
|
11
|
+
# Read a value from a pointer at a given index
|
12
|
+
# (Type can be a byte-array, pointer or numeric type)
|
13
|
+
def self.fetch_single(pointer, native: false)
|
14
|
+
# Nothing to fetch for Nils
|
15
|
+
return if memsize.zero?
|
16
|
+
|
17
|
+
if numeric?
|
18
|
+
pointer.send("read_#{ffi_type}")
|
19
|
+
elsif primitive?
|
20
|
+
single = new(pointer.send("read_#{ffi_type}"))
|
21
|
+
if native
|
22
|
+
single.value
|
23
|
+
else
|
24
|
+
single
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
# Write a data type into a pointer at a given index
|
30
|
+
# (Type can be a byte-array, pointer or numeric type)
|
31
|
+
def self.write_single(pointer, value)
|
32
|
+
# Dont need to write nils
|
33
|
+
return if memsize.zero?
|
34
|
+
|
35
|
+
pointer.send("write_#{ffi_type}", to_ffi_repr(value))
|
36
|
+
end
|
37
|
+
|
38
|
+
# Fetch an array of a given data type from a list pointer
|
39
|
+
# (Type can be a byte-array, pointer or numeric type)
|
40
|
+
def self.fetch_multi(pointer, size, native: false)
|
41
|
+
if numeric?
|
42
|
+
pointer.send("get_array_of_#{ffi_type}", 0, size)
|
43
|
+
elsif primitive?
|
44
|
+
pointer.send("get_array_of_#{ffi_type}", 0, size).map(&method(:from_ffi_array_repr))
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def self.decrement_ref_count!(pointer)
|
49
|
+
# Do nothing
|
50
|
+
end
|
51
|
+
|
52
|
+
# Define a new primitive type
|
53
|
+
# Primitive types are stored by value
|
54
|
+
# and efficiently copied using native FFI types
|
55
|
+
# They are written directly into the memory of a container type
|
56
|
+
# (No indirection)
|
57
|
+
def self.build(
|
58
|
+
typename = nil,
|
59
|
+
ffi_type: :uint8,
|
60
|
+
memsize: FFI.type_size(ffi_type),
|
61
|
+
convert_if: [],
|
62
|
+
error: nil,
|
63
|
+
superclass: Primitive,
|
64
|
+
&block
|
65
|
+
)
|
66
|
+
Class.new(superclass) do
|
67
|
+
%w[typename ffi_type memsize convert_if error].each do |name|
|
68
|
+
define_singleton_method(name) { binding.local_variable_get("#{name}") }
|
69
|
+
define_method(name) { binding.local_variable_get("#{name}") }
|
70
|
+
end
|
71
|
+
|
72
|
+
class_eval(&block) if block_given?
|
73
|
+
|
74
|
+
# Primitives are stored directly in memory as a raw numeric value
|
75
|
+
def self.to_ffi_repr(value)
|
76
|
+
new(value).inner_value
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.refsize
|
80
|
+
memsize
|
81
|
+
end
|
82
|
+
|
83
|
+
# Primiives are anonymous (Shouldn't be subclassed)
|
84
|
+
def self.anonymous?
|
85
|
+
true
|
86
|
+
end
|
87
|
+
|
88
|
+
def self.copy_to!(rbval, memory:)
|
89
|
+
memory.send("write_#{self.ffi_type}", to_ffi_repr(rbval))
|
90
|
+
end
|
91
|
+
|
92
|
+
def self.primitive?
|
93
|
+
true
|
94
|
+
end
|
95
|
+
|
96
|
+
def self.inspect
|
97
|
+
inspect_name
|
98
|
+
end
|
99
|
+
|
100
|
+
def memory
|
101
|
+
@value
|
102
|
+
end
|
103
|
+
|
104
|
+
def self.crystal_supertype
|
105
|
+
"CrystalRuby::Types::Primitive"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
require_relative "primitive_types/time"
|
114
|
+
require_relative "primitive_types/symbol"
|
115
|
+
require_relative "primitive_types/numbers"
|
116
|
+
require_relative "primitive_types/nil"
|
117
|
+
require_relative "primitive_types/bool"
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class <%= base_crystal_class_name %> < CrystalRuby::Types::Primitive
|
2
|
+
|
3
|
+
def initialize(value : ::Bool)
|
4
|
+
@value = value ? 1_u8 : 0_u8
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(ptr : Pointer(::UInt8))
|
8
|
+
@value = ptr[0]
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(value : UInt8)
|
12
|
+
@value = value
|
13
|
+
end
|
14
|
+
|
15
|
+
def value=(value : ::Bool)
|
16
|
+
@value = value ? 1_u8 : 0_u8
|
17
|
+
end
|
18
|
+
|
19
|
+
def value : <%= native_type_expr %>
|
20
|
+
@value == 1_u8
|
21
|
+
end
|
22
|
+
|
23
|
+
def ==(other : ::Bool)
|
24
|
+
value == other
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.memsize
|
28
|
+
<%= memsize %>
|
29
|
+
end
|
30
|
+
|
31
|
+
def self.write_single(pointer : Pointer(::UInt8), value)
|
32
|
+
pointer.as(Pointer(::UInt8)).value = value ? 1_u8 : 0_u8
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module CrystalRuby::Types
|
2
|
+
Bool = Primitive.build(:Bool, convert_if: [::TrueClass, ::FalseClass], ffi_type: :uint8, memsize: 1) do
|
3
|
+
def value(native: false)
|
4
|
+
super == 1
|
5
|
+
end
|
6
|
+
|
7
|
+
def value=(val)
|
8
|
+
!!val && val != 0 ? super(1) : super(0)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class <%= base_crystal_class_name %> < CrystalRuby::Types::Primitive
|
2
|
+
|
3
|
+
property value : ::Nil = nil
|
4
|
+
|
5
|
+
def initialize(nilval : ::Nil)
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(ptr : Pointer(::UInt8))
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(raw : UInt8)
|
12
|
+
end
|
13
|
+
|
14
|
+
def value : ::Nil
|
15
|
+
nil
|
16
|
+
end
|
17
|
+
|
18
|
+
def ==(other : ::Nil)
|
19
|
+
value.nil?
|
20
|
+
end
|
21
|
+
|
22
|
+
def value=(val : ::Nil)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.memsize
|
26
|
+
0
|
27
|
+
end
|
28
|
+
|
29
|
+
def return_value
|
30
|
+
0_u8
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.write_single(pointer : Pointer(::UInt8), value)
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
class <%= base_crystal_class_name %> < CrystalRuby::Types::Primitive
|
2
|
+
|
3
|
+
def initialize(value : <%= native_type_expr %>)
|
4
|
+
@value = value
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(ptr : Pointer(::UInt8))
|
8
|
+
@value = ptr.as(Pointer( <%= native_type_expr %>))[0]
|
9
|
+
end
|
10
|
+
|
11
|
+
def value
|
12
|
+
@value
|
13
|
+
end
|
14
|
+
|
15
|
+
def ==(other : <%= native_type_expr %>)
|
16
|
+
value == other
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.memsize
|
20
|
+
<%= memsize %>
|
21
|
+
end
|
22
|
+
|
23
|
+
def value=(value : <%= native_type_expr %>)
|
24
|
+
@value = value
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.copy_to!(value : <%= native_type_expr %>, ptr : Pointer(::UInt8))
|
28
|
+
ptr.as(Pointer( <%= native_type_expr %>))[0] = value
|
29
|
+
end
|
30
|
+
|
31
|
+
# Write a data type into a pointer at a given index
|
32
|
+
# (Type can be a byte-array, pointer or numeric type)
|
33
|
+
def self.write_single(pointer : Pointer(::UInt8), value)
|
34
|
+
pointer.as(Pointer( <%= native_type_expr %>)).value = value
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module CrystalRuby::Types
|
2
|
+
%i[UInt8 UInt16 UInt32 UInt64 Int8 Int16 Int32 Int64 Float32 Float64].each do |type_name|
|
3
|
+
ffi_type = CrystalRuby::Typemaps::FFI_TYPE_MAP.fetch(type_name.to_s)
|
4
|
+
const_set(type_name, Primitive.build(type_name, convert_if: [::Numeric], ffi_type: ffi_type) do
|
5
|
+
def value=(val)
|
6
|
+
raise "Expected a numeric value, got #{val}" unless val.is_a?(::Numeric)
|
7
|
+
|
8
|
+
super(typename.to_s.start_with?("Float") ? val.to_f : val.to_i)
|
9
|
+
end
|
10
|
+
|
11
|
+
def value(native: false)
|
12
|
+
@value
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.from_ffi_array_repr(value)
|
16
|
+
value
|
17
|
+
end
|
18
|
+
|
19
|
+
def self.numeric?
|
20
|
+
true
|
21
|
+
end
|
22
|
+
|
23
|
+
def self.template_name
|
24
|
+
"Numbers"
|
25
|
+
end
|
26
|
+
end)
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
class <%= base_crystal_class_name %> < CrystalRuby::Types::Primitive
|
2
|
+
|
3
|
+
def initialize(value : ::Symbol)
|
4
|
+
@value = 0.to_u32
|
5
|
+
self.value = value
|
6
|
+
end
|
7
|
+
|
8
|
+
def initialize(value : UInt32)
|
9
|
+
@value = value
|
10
|
+
end
|
11
|
+
|
12
|
+
def initialize(ptr : Pointer(::UInt8))
|
13
|
+
initialize(ptr.as(Pointer(::UInt32))[0])
|
14
|
+
end
|
15
|
+
|
16
|
+
def ==(other : ::Symbol)
|
17
|
+
value == other
|
18
|
+
end
|
19
|
+
|
20
|
+
def value=(value : ::Symbol)
|
21
|
+
case value
|
22
|
+
<% allowed_values.each_with_index do |v, i| %>
|
23
|
+
when :<%= v %> then @value = <%= i %>.to_u32
|
24
|
+
<% end %>
|
25
|
+
else raise "Symbol must be one of <%= allowed_values %>. Got #{value}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def value : ::Symbol
|
30
|
+
case @value
|
31
|
+
<% allowed_values.each_with_index do |v, i| %>
|
32
|
+
when <%= i %> then :<%= v %>
|
33
|
+
<% end %>
|
34
|
+
else raise "Symbol must be one of <%= allowed_values %>. Got #{value}"
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def self.copy_to!(value : ::Symbol, ptr : Pointer(::UInt8))
|
39
|
+
ptr.as(Pointer(::UInt32))[0] = new(value).return_value
|
40
|
+
end
|
41
|
+
|
42
|
+
def self.memsize
|
43
|
+
<%= memsize %>
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.write_single(pointer : Pointer(::UInt8), value)
|
47
|
+
as_uint32 = case value
|
48
|
+
<% allowed_values.each_with_index do |v, i| %>
|
49
|
+
when :<%= v %> then <%= i %>.to_u32
|
50
|
+
<% end %>
|
51
|
+
else raise "Symbol must be one of <%= allowed_values %>. Got #{value}"
|
52
|
+
end
|
53
|
+
pointer.as(Pointer(::UInt32)).value = as_uint32
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module CrystalRuby::Types
|
2
|
+
Symbol = Primitive.build(
|
3
|
+
error: "Symbol CrystalRuby types should indicate a list of possible values shared between Crystal and Ruby. "\
|
4
|
+
"E.g. Symbol(:green, :blue, :orange). If this list is not known at compile time, you should use a String instead."
|
5
|
+
)
|
6
|
+
|
7
|
+
def self.Symbol(*allowed_values)
|
8
|
+
raise "Symbol must have at least one value" if allowed_values.empty?
|
9
|
+
|
10
|
+
allowed_values.flatten!
|
11
|
+
raise "Symbol allowed values must all be symbols" unless allowed_values.all? { |v| v.is_a?(::Symbol) }
|
12
|
+
|
13
|
+
Primitive.build(:Symbol, ffi_type: :uint32, convert_if: [Root::String, Root::Symbol], memsize: 4) do
|
14
|
+
bind_local_vars!(%i[allowed_values], binding)
|
15
|
+
define_method(:value=) do |val|
|
16
|
+
val = allowed_values[val] if val.is_a?(::Integer) && val >= 0 && val < allowed_values.size
|
17
|
+
raise "Symbol must be one of #{allowed_values}" unless allowed_values.include?(val)
|
18
|
+
|
19
|
+
super(allowed_values.index(val))
|
20
|
+
end
|
21
|
+
|
22
|
+
define_singleton_method(:valid_cast?) do |raw|
|
23
|
+
super(raw) && allowed_values.include?(raw)
|
24
|
+
end
|
25
|
+
|
26
|
+
define_method(:value) do |native: false|
|
27
|
+
allowed_values[super()]
|
28
|
+
end
|
29
|
+
|
30
|
+
define_singleton_method(:type_digest) do
|
31
|
+
Digest::MD5.hexdigest(native_type_expr.to_s + allowed_values.map(&:to_s).join(","))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
class <%= base_crystal_class_name %> < CrystalRuby::Types::Primitive
|
2
|
+
|
3
|
+
def initialize(time : ::Time)
|
4
|
+
@value = time.to_unix_ns / 1000_000_000.0
|
5
|
+
end
|
6
|
+
|
7
|
+
def initialize(ptr : Pointer(::UInt8))
|
8
|
+
@value = ptr.as(Pointer(::Float64)).value
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(@value : ::Float64)
|
12
|
+
end
|
13
|
+
|
14
|
+
def ==(other : ::Time)
|
15
|
+
value == other
|
16
|
+
end
|
17
|
+
|
18
|
+
def value=(time : ::Time)
|
19
|
+
@value = time.to_unix_ns / 1000_000_000.0
|
20
|
+
end
|
21
|
+
|
22
|
+
def value : ::Time
|
23
|
+
::Time.unix_ns((@value * 1000_000_000).to_i128)
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.memsize
|
27
|
+
<%= memsize %>
|
28
|
+
end
|
29
|
+
|
30
|
+
|
31
|
+
def self.write_single(pointer : Pointer(::UInt8), time)
|
32
|
+
pointer.as(Pointer(::Float64)).value = time.to_unix_ns / 1000_000_000.0
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "date"
|
4
|
+
|
5
|
+
module CrystalRuby::Types
|
6
|
+
Time = Primitive.build(:Time, convert_if: [Root::Time, Root::String, DateTime], ffi_type: :double) do
|
7
|
+
def initialize(val = Root::Time.now)
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def value=(val)
|
12
|
+
super(
|
13
|
+
if val.respond_to?(:to_time)
|
14
|
+
val.to_time.to_f
|
15
|
+
else
|
16
|
+
val.respond_to?(:to_f) ? val.to_f : 0
|
17
|
+
end
|
18
|
+
)
|
19
|
+
end
|
20
|
+
|
21
|
+
def value(native: false)
|
22
|
+
::Time.at(super)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module CrystalRuby
|
2
|
+
module Types
|
3
|
+
class Type
|
4
|
+
property memory : Pointer(::UInt8) = Pointer(::UInt8).null
|
5
|
+
|
6
|
+
macro method_missing(call)
|
7
|
+
current_value = self.native
|
8
|
+
current_hash = current_value.hash
|
9
|
+
return_value = current_value.{{ call }}
|
10
|
+
|
11
|
+
if current_hash != current_value.hash
|
12
|
+
self.value = current_value
|
13
|
+
end
|
14
|
+
return_value
|
15
|
+
end
|
16
|
+
|
17
|
+
def to_s
|
18
|
+
native.to_s
|
19
|
+
end
|
20
|
+
|
21
|
+
def synchronize
|
22
|
+
CrystalRuby.synchronize do
|
23
|
+
yield
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.synchronize
|
28
|
+
yield
|
29
|
+
end
|
30
|
+
|
31
|
+
def variable_width?
|
32
|
+
false
|
33
|
+
end
|
34
|
+
|
35
|
+
def return_value
|
36
|
+
memory
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.free(memory : Pointer(::UInt8))
|
40
|
+
LibC.free(memory)
|
41
|
+
end
|
42
|
+
|
43
|
+
def self.malloc(size : Int) : Pointer(::UInt8)
|
44
|
+
LibC.calloc(size, 1).as(Pointer(::UInt8))
|
45
|
+
end
|
46
|
+
|
47
|
+
def malloc(memsize)
|
48
|
+
self.class.malloc(memsize)
|
49
|
+
end
|
50
|
+
|
51
|
+
def self.each_child_address(pointer : Pointer(::UInt8), &block : Pointer(::UInt8) -> Nil)
|
52
|
+
# Do nothing
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.fetch_multi!(pointer : Pointer(::UInt8), size)
|
56
|
+
size.times.map { |i| fetch_single(pointer + i * refsize) }.to_a
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.fetch_multi_native!(pointer : Pointer(::UInt8), size)
|
60
|
+
size.times.map { |i| fetch_single(pointer + i * refsize).native }.to_a
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|