Class: MessagePack::Inspect::Node

Inherits:
Object
  • Object
show all
Defined in:
lib/msgpack/inspect/node.rb

Constant Summary collapse

FORMATS =
[
  :fixint, :uint8, :uint16, :uint32, :uint64, :int8, :int16, :int32, :int64,
  :fixmap, :map16, :map32,
  :fixarray, :array16, :array32,
  :fixstr, :str8, :str16, :str32,
  :nil, :false, :true,
  :bin8, :bin16, :bin32,
  :ext8, :ext16, :ext32, :fixext1, :fixext2, :fixext4, :fixext8, :fixext16,
  :float32, :float64,
  :never_used,
]
ARRAYS =
[:fixarray, :array16, :array32]
MAPS =
[:fixmap, :map16, :map32]
MAX_INT16 =
2 ** 16
MAX_INT32 =
2 ** 32
MAX_INT64 =
2 ** 64
MSGPACK_LOADED =
MessagePack.const_defined?('Unpacker')

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(format, header) ⇒ Node

Returns a new instance of Node.



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
# File 'lib/msgpack/inspect/node.rb', line 27

def initialize(format, header)
  raise "unknown format specifier: #{format}" unless FORMATS.include?(format)
  @format = format
  @header = header # call #hex to dump
  @length = @exttype = @data = @value = @children = @error = nil

  case @format
  when :fixmap, :map16, :map32, :fixarray, :array16, :array32
    @children = []
  when :nil
    @data = hex(header)
    @value = nil
  when :false
    @data = hex(header)
    @value = false
  when :true
    @data = hex(header)
    @value = true
  when :never_used
    @data = hex(header)
    @error = "msgpack format 'NEVER USED' specified"
  end

  @first_line = true
  @first_obj = true
  @first_kv_pair = true
end

Instance Attribute Details

#childrenObject

header: hex (binary) exttype: hex (value) length: numeric data: hex value: object children: (array of Node for array, array of Hash, which has keys of :key and :value for map)



10
11
12
# File 'lib/msgpack/inspect/node.rb', line 10

def children
  @children
end

#dataObject

header: hex (binary) exttype: hex (value) length: numeric data: hex value: object children: (array of Node for array, array of Hash, which has keys of :key and :value for map)



10
11
12
# File 'lib/msgpack/inspect/node.rb', line 10

def data
  @data
end

#depthObject

Returns the value of attribute depth.



11
12
13
# File 'lib/msgpack/inspect/node.rb', line 11

def depth
  @depth
end

#errorObject

header: hex (binary) exttype: hex (value) length: numeric data: hex value: object children: (array of Node for array, array of Hash, which has keys of :key and :value for map)



10
11
12
# File 'lib/msgpack/inspect/node.rb', line 10

def error
  @error
end

#exttypeObject

header: hex (binary) exttype: hex (value) length: numeric data: hex value: object children: (array of Node for array, array of Hash, which has keys of :key and :value for map)



10
11
12
# File 'lib/msgpack/inspect/node.rb', line 10

def exttype
  @exttype
end

#formatObject

header: hex (binary) exttype: hex (value) length: numeric data: hex value: object children: (array of Node for array, array of Hash, which has keys of :key and :value for map)



10
11
12
# File 'lib/msgpack/inspect/node.rb', line 10

def format
  @format
end

#headerObject

header: hex (binary) exttype: hex (value) length: numeric data: hex value: object children: (array of Node for array, array of Hash, which has keys of :key and :value for map)



10
11
12
# File 'lib/msgpack/inspect/node.rb', line 10

def header
  @header
end

#headingObject

Returns the value of attribute heading.



11
12
13
# File 'lib/msgpack/inspect/node.rb', line 11

def heading
  @heading
end

#ioObject

Returns the value of attribute io.



11
12
13
# File 'lib/msgpack/inspect/node.rb', line 11

def io
  @io
end

#lengthObject

header: hex (binary) exttype: hex (value) length: numeric data: hex value: object children: (array of Node for array, array of Hash, which has keys of :key and :value for map)



10
11
12
# File 'lib/msgpack/inspect/node.rb', line 10

def length
  @length
end

#valueObject

header: hex (binary) exttype: hex (value) length: numeric data: hex value: object children: (array of Node for array, array of Hash, which has keys of :key and :value for map)



10
11
12
# File 'lib/msgpack/inspect/node.rb', line 10

def value
  @value
end

Instance Method Details

#<<(child) ⇒ Object



284
285
286
287
# File 'lib/msgpack/inspect/node.rb', line 284

def <<(child)
  raise "adding child object to non-array object" unless is_array?
  @children << child
end

#[]=(key, value) ⇒ Object



289
290
291
292
# File 'lib/msgpack/inspect/node.rb', line 289

def []=(key, value)
  raise "adding key-value objects to non-map object" unless is_map?
  @children << {key => value}
end

#attributes(io) ⇒ Object



73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
# File 'lib/msgpack/inspect/node.rb', line 73

def attributes(io)
  # read attributes from io
  case @format
  when :fixarray, :array16, :array32
    attributes_array(io)
  when :fixmap, :map16, :map32
    attributes_map(io)
  when :nil, :false, :true, :never_used
    # nothing to do...
  when :fixint, :uint8, :uint16, :uint32, :uint64, :int8, :int16, :int32, :int64
    attributes_int(io)
  when :float32, :float64
    attributes_float(io)
  when :fixstr, :str8, :str16, :str32, :bin8, :bin16, :bin32
    attributes_string(io)
  when :ext8, :ext16, :ext32, :fixext1, :fixext2, :fixext4, :fixext8, :fixext16
    attributes_ext(io)
  end
end

#attributes_array(io) ⇒ Object



93
94
95
96
97
98
99
100
101
102
103
104
# File 'lib/msgpack/inspect/node.rb', line 93

def attributes_array(io)
  @length = case @format
            when :fixarray
              @header.unpack('C').first & 0x0f
            when :array16
              io.read(2).unpack('n').first
            when :array32
              io.read(4).unpack('N').first
            else
              raise "unknown array fmt #{@format}"
            end
end

#attributes_ext(io) ⇒ Object



242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
# File 'lib/msgpack/inspect/node.rb', line 242

def attributes_ext(io)
  data = ''.b
  @length = case @format
            when :fixext1 then 1
            when :fixext2 then 2
            when :fixext4 then 4
            when :fixext8 then 8
            when :fixext16 then 16
            when :ext8
              v = io.read(1)
              data << v
              v.unpack('C').first
            when :ext16
              v = io.read(2)
              data << v
              v.unpack('n').first
            when :ext32
              v = io.read(4)
              data << v
              v.unpack('N').first
            else
              raise "unknown ext format #{@format}"
            end
  v = io.read(1)
  @exttype = v.unpack('c').first
  val = io.read(@length)
  @data = hex(val)
  @value = if MSGPACK_LOADED
             MessagePack.unpack(val)
           else
             nil
           end
end

#attributes_float(io) ⇒ Object



199
200
201
202
203
204
205
206
207
208
209
210
211
212
# File 'lib/msgpack/inspect/node.rb', line 199

def attributes_float(io)
  case @format
  when :float32
    v = io.read(4)
    @data = hex(v)
    @value = v.unpack('g').first
  when :float64
    v = io.read(8)
    @data = hex(v)
    @value = v.unpack('G').first
  else
    raise "unknown float format #{@format}"
  end
end

#attributes_int(io) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
# File 'lib/msgpack/inspect/node.rb', line 123

def attributes_int(io)
  if @format == :fixint
    @data = hex(@header)
    v = @header.unpack('C').first
    @value = if v & 0b11100000 > 0 # negative fixint
               @header.unpack('c').first
             else # positive fixint
               @header.unpack('C').first
             end
    return
  end

  case @format
  when :uint8
    v = io.read(1)
    @data = hex(v)
    @value = v.unpack('C').first
  when :uint16
    v = io.read(2)
    @data = hex(v)
    @value = v.unpack('n').first
  when :uint32
    v = io.read(4)
    @data = hex(v)
    @value = v.unpack('N').first
  when :uint64
    v1 = io.read(4)
    v2 = io.read(4)
    @data = hex(v1) + hex(v2)
    # mruby doesn't have Bignum, and Float doesn't support #|
    # @value = (v1.unpack('N').first << 32) | v2.unpack('N').first
    @value = (v1.unpack('N').first << 32) + v2.unpack('N').first
  when :int8
    v = io.read(1)
    @data = hex(v)
    @value = v.unpack('c').first
  when :int16
    v = io.read(2)
    @data = hex(v)
    n = v.unpack('n').first
    @value = if (n & 0x8000) > 0 # negative
               n - MAX_INT16
             else
               n
             end
  when :int32
    v = io.read(4)
    @data = hex(v)
    n = v.unpack('N').first
    @value = if n & 0x80000000 > 0 # negative
               n - MAX_INT32
             else
               n
             end
  when :int64
    v1 = io.read(4)
    v2 = io.read(4)
    @data = hex(v1) + hex(v2)
    # mruby doesn't have Bignum, and Float doesn't support #|
    # n = (v1.unpack('N').first << 32) | v2.unpack('N').first
    # @value = if n & 0x8000_0000_0000_0000 > 0 # negative
    #            n - MAX_INT64
    #          else
    #            n
    #          end
    upper = v1.unpack('N').first
    @value = if upper & 0x8000_0000 > 0 # negative
               (upper << 32) + v2.unpack('N').first - MAX_INT64
             else # positive
               (upper << 32) + v2.unpack('N').first
             end
  else
    raise "unknown int format #{@format}"
  end
end

#attributes_map(io) ⇒ Object



106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/msgpack/inspect/node.rb', line 106

def attributes_map(io)
  @length = case @format
            when :fixmap
              @header.unpack('C').first & 0x0f
            when :map16
              io.read(2).unpack('n').first
            when :map32
              io.read(4).unpack('N').first
            else
              raise "unknown map fmt #{@format}"
            end
end

#attributes_string(io) ⇒ Object



214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
# File 'lib/msgpack/inspect/node.rb', line 214

def attributes_string(io)
  @length = case @format
            when :fixstr
              @header.unpack('C').first & 0b00011111
            when :str8, :bin8
              io.read(1).unpack('C').first
            when :str16, :bin16
              io.read(2).unpack('n').first
            when :str32, :bin32
              io.read(4).unpack('N').first
            else
              raise "unknown string format #{@format}"
            end
  v = io.read(@length)
  @data = hex(v)
  if [:fixstr, :str8, :str16, :str32].include?(@format)
    begin
      @value = v.force_encoding('UTF-8')
    rescue => e
      @error = e.message
    end
  else
    @value = v.b
  end
end

#element_keyObject



65
66
67
# File 'lib/msgpack/inspect/node.rb', line 65

def element_key
  yield
end

#element_valueObject



69
70
71
# File 'lib/msgpack/inspect/node.rb', line 69

def element_value
  yield
end

#elements(&block) ⇒ Object



59
60
61
62
63
# File 'lib/msgpack/inspect/node.rb', line 59

def elements(&block)
  @length.times do |i|
    yield i
  end
end

#hex(str) ⇒ Object



55
56
57
# File 'lib/msgpack/inspect/node.rb', line 55

def hex(str)
  str.unpack("H*").first
end

#is_array?Boolean

Returns:

  • (Boolean)


276
277
278
# File 'lib/msgpack/inspect/node.rb', line 276

def is_array?
  ARRAYS.include?(@format)
end

#is_map?Boolean

Returns:

  • (Boolean)


280
281
282
# File 'lib/msgpack/inspect/node.rb', line 280

def is_map?
  MAPS.include?(@format)
end