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
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
|
# File 'lib/capnp/runtime/list/buffer/list.rb', line 38
def self.from_pointer(pointer_ref)
pointer_ref, content_ref = pointer_ref.segment.message.dereference_pointer(pointer_ref)
pointer_data = pointer_ref.read_bytes(0, Capnp::WORD_SIZE)
offset_part, size_part = T.cast(pointer_data.unpack("l<L<"), [Integer, Integer])
return nil if offset_part.zero? && size_part.zero?
pointer_type = offset_part & 0b11
raise Capnp::Error.new("List pointer has type #{pointer_type}") unless pointer_type == 1
length = size_part >> 3
element_type = size_part & 0b111
element_size = case element_type
when 0 then 0
when 1 then 1
when 2, 3, 4, 5 then 1 << (element_type - 2)
when 6 then Capnp::WORD_SIZE
else
0 end
if content_ref.nil?
data_offset = ((offset_part >> 2) + 1) * Capnp::WORD_SIZE
data_ref = pointer_ref.offset_position(data_offset)
else
data_ref = content_ref
end
data_words = 0
pointers_words = 0
if element_type == 7
length, data_words, pointers_words = Capnp::Struct.decode_pointer(data_ref)
data_ref = data_ref.offset_position(Capnp::WORD_SIZE)
element_size = (data_words + pointers_words) * Capnp::WORD_SIZE
end
new(data_ref, length, element_type, element_size, data_words, pointers_words)
end
|