Class: Erlang::Decode
Defined Under Namespace
Classes: DecodeError
Constant Summary
External::Types::ATOM, External::Types::BIN, External::Types::FLOAT, External::Types::FUN, External::Types::INT, External::Types::LARGE_BIGNUM, External::Types::LARGE_TUPLE, External::Types::LIST, External::Types::NEW_FLOAT, External::Types::NEW_FUN, External::Types::NEW_REF, External::Types::NIL, External::Types::PID, External::Types::PORT, External::Types::REF, External::Types::SMALL_BIGNUM, External::Types::SMALL_INT, External::Types::SMALL_TUPLE, External::Types::STRING
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize(ins) ⇒ Decode
Returns a new instance of Decode.
16
17
18
19
|
# File 'lib/rinterface/erlang/decoder.rb', line 16
def initialize(ins)
@in = ins
@peeked = ""
end
|
Instance Attribute Details
#in ⇒ Object
Returns the value of attribute in.
6
7
8
|
# File 'lib/rinterface/erlang/decoder.rb', line 6
def in
@in
end
|
Class Method Details
.read_any_from(string) ⇒ Object
12
13
14
|
# File 'lib/rinterface/erlang/decoder.rb', line 12
def self.read_any_from(string)
new(StringIO.new(string)).read_any
end
|
.read_bits(string) ⇒ Object
8
9
10
|
# File 'lib/rinterface/erlang/decoder.rb', line 8
def self.read_bits(string)
new(StringIO.new(string))
end
|
Instance Method Details
#fail(str) ⇒ Object
217
218
219
|
# File 'lib/rinterface/erlang/decoder.rb', line 217
def fail(str)
raise DecodeError, str
end
|
#peek(length) ⇒ Object
66
67
68
69
70
71
72
73
74
|
# File 'lib/rinterface/erlang/decoder.rb', line 66
def peek(length)
if length <= @peeked.length
@peeked[0...length]
else
read_bytes = @in.read(length - @peeked.length)
@peeked << read_bytes if read_bytes
@peeked
end
end
|
#peek_1 ⇒ Object
76
77
78
|
# File 'lib/rinterface/erlang/decoder.rb', line 76
def peek_1
peek(1).unpack("C").first
end
|
#peek_2 ⇒ Object
80
81
82
|
# File 'lib/rinterface/erlang/decoder.rb', line 80
def peek_2
peek(2).unpack("n").first
end
|
#read(length) ⇒ Object
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
# File 'lib/rinterface/erlang/decoder.rb', line 48
def read(length)
if length < @peeked.length
result = @peeked[0...length]
@peeked = @peeked[length..-1]
length = 0
else
result = @peeked
@peeked = ''
length -= result.length
end
if length > 0
result << @in.read(length)
end
result
end
|
#read_1 ⇒ Object
84
85
86
|
# File 'lib/rinterface/erlang/decoder.rb', line 84
def read_1
read(1).unpack("C").first
end
|
#read_2 ⇒ Object
88
89
90
|
# File 'lib/rinterface/erlang/decoder.rb', line 88
def read_2
read(2).unpack("n").first
end
|
#read_4 ⇒ Object
92
93
94
|
# File 'lib/rinterface/erlang/decoder.rb', line 92
def read_4
read(4).unpack("N").first
end
|
#read_any ⇒ Object
21
22
23
24
|
# File 'lib/rinterface/erlang/decoder.rb', line 21
def read_any
raise "Bad Math on Version" unless read_1 == External::VERSION
read_any_raw
end
|
#read_any_raw ⇒ Object
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
|
# File 'lib/rinterface/erlang/decoder.rb', line 26
def read_any_raw
case peek_1
when ATOM then read_atom
when SMALL_INT then read_small_int
when INT then read_int
when SMALL_BIGNUM then read_small_bignum
when LARGE_BIGNUM then read_large_bignum
when NEW_FLOAT then read_double
when FLOAT then read_float
when NEW_REF then read_new_reference
when PID then read_pid
when SMALL_TUPLE then read_small_tuple
when LARGE_TUPLE then read_large_tuple
when NIL then read_nil
when STRING then read_erl_string
when LIST then read_list
when BIN then read_bin
else
fail("Unknown term tag: #{peek_1}")
end
end
|
#read_atom ⇒ Object
100
101
102
103
104
105
106
107
108
|
# File 'lib/rinterface/erlang/decoder.rb', line 100
def read_atom
fail("Invalid Type, not an atom") unless read_1 == ATOM
length = read_2
if length == 0
''
else
read_string(length).to_sym
end
end
|
#read_bin ⇒ Object
210
211
212
213
214
|
# File 'lib/rinterface/erlang/decoder.rb', line 210
def read_bin
fail("Invalid Type, not an erlang binary") unless read_1 == BIN
length = read_4
read_string(length)
end
|
#read_double ⇒ Object
149
150
151
152
|
# File 'lib/rinterface/erlang/decoder.rb', line 149
def read_double
fail("Invalid Type, not a double") unless read_1 == NEW_FLOAT
read_string(64).unpack('G').first
end
|
#read_erl_string ⇒ Object
196
197
198
199
200
|
# File 'lib/rinterface/erlang/decoder.rb', line 196
def read_erl_string
fail("Invalid Type, not an erlang string") unless read_1 == STRING
length = read_2
read_string(length).unpack('C' * length)
end
|
#read_float ⇒ Object
154
155
156
157
158
|
# File 'lib/rinterface/erlang/decoder.rb', line 154
def read_float
fail("Invalid Type, not a float") unless read_1 == FLOAT
read_string(32).unpack('g').first
end
|
#read_int ⇒ Object
115
116
117
118
119
120
121
|
# File 'lib/rinterface/erlang/decoder.rb', line 115
def read_int
fail("Invalid Type, not an int") unless read_1 == INT
value = read_4
negative = (value >> 31)[0] == 1
value = (value - (1 << 32)) if negative
value = Fixnum.induced_from(value)
end
|
#read_large_bignum ⇒ Object
136
137
138
139
140
141
142
143
144
145
146
147
|
# File 'lib/rinterface/erlang/decoder.rb', line 136
def read_large_bignum
fail("Invalid Type, not a large bignum") unless read_1 == LARGE_BIGNUM
size = read_4
sign = read_1
bytes = read_string(size).unpack("C" * size)
added = bytes.zip((0..bytes.length).to_a).inject(0) do |result, byte_index|
byte, index = *byte_index
value = (byte * (256 ** index))
sign != 0 ? (result - value) : (result + value)
end
Bignum.induced_from(added)
end
|
#read_large_tuple ⇒ Object
185
186
187
188
189
|
# File 'lib/rinterface/erlang/decoder.rb', line 185
def read_large_tuple
fail("Invalid Type, not a small tuple") unless read_1 == LARGE_TUPLE
arity = read_4
(0...arity).map{|i| read_any_raw}
end
|
#read_list ⇒ Object
202
203
204
205
206
207
208
|
# File 'lib/rinterface/erlang/decoder.rb', line 202
def read_list
fail("Invalid Type, not an erlang list") unless read_1 == LIST
length = read_4
list = (0...length).map{|i| read_any_raw}
read_1
list
end
|
#read_new_reference ⇒ Object
160
161
162
163
164
165
166
167
|
# File 'lib/rinterface/erlang/decoder.rb', line 160
def read_new_reference
fail("Invalid Type, not a new-style reference") unless read_1 == NEW_REF
size = read_2
node = read_atom
creation = read_1
id = (0...size).map{|i| read_4 }
NewReference.new(node, creation, id)
end
|
#read_nil ⇒ Object
191
192
193
194
|
# File 'lib/rinterface/erlang/decoder.rb', line 191
def read_nil
fail("Invalid Type, not a nil list") unless read_1 == NIL
[]
end
|
#read_pid ⇒ Object
169
170
171
172
173
174
175
176
|
# File 'lib/rinterface/erlang/decoder.rb', line 169
def read_pid
fail("Invalid Type, not a pid") unless read_1 == PID
node = read_atom
id = read_4
serial = read_4
creation = read_1
Terms::Pid.new(node, id, serial, creation)
end
|
#read_small_bignum ⇒ Object
123
124
125
126
127
128
129
130
131
132
133
134
|
# File 'lib/rinterface/erlang/decoder.rb', line 123
def read_small_bignum
fail("Invalid Type, not a small bignum") unless read_1 == SMALL_BIGNUM
size = read_1
sign = read_1
bytes = read_string(size).unpack("C" * size)
added = bytes.zip((0..bytes.length).to_a).inject(0) do |result, byte_index|
byte, index = *byte_index
value = (byte * (256 ** index))
sign != 0 ? (result - value) : (result + value)
end
Bignum.induced_from(added)
end
|
#read_small_int ⇒ Object
110
111
112
113
|
# File 'lib/rinterface/erlang/decoder.rb', line 110
def read_small_int
fail("Invalid Type, not a small int") unless read_1 == SMALL_INT
read_1
end
|
#read_small_tuple ⇒ Object
178
179
180
181
182
183
|
# File 'lib/rinterface/erlang/decoder.rb', line 178
def read_small_tuple
fail("Invalid Type, not a small tuple") unless read_1 == SMALL_TUPLE
arity = read_1
(0...arity).map{|i| read_any_raw }
end
|
#read_string(length) ⇒ Object
96
97
98
|
# File 'lib/rinterface/erlang/decoder.rb', line 96
def read_string(length)
read(length)
end
|