Class: BinaryCodec::BinaryParser

Inherits:
Object
  • Object
show all
Defined in:
lib/binary-codec/serdes/binary_parser.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(hex_bytes = '') ⇒ BinaryParser



9
10
11
12
# File 'lib/binary-codec/serdes/binary_parser.rb', line 9

def initialize(hex_bytes = '')
  @bytes = hex_to_bytes(hex_bytes)
  @definitions = Definitions.instance
end

Instance Attribute Details

#definitionsObject (readonly)

Returns the value of attribute definitions.



7
8
9
# File 'lib/binary-codec/serdes/binary_parser.rb', line 7

def definitions
  @definitions
end

Instance Method Details

#end?(custom_end = nil) ⇒ Boolean



61
62
63
64
# File 'lib/binary-codec/serdes/binary_parser.rb', line 61

def end?(custom_end = nil)
  length = @bytes.length
  length == 0 || (!custom_end.nil? && length <= custom_end)
end

#peekObject



14
15
16
17
18
19
# File 'lib/binary-codec/serdes/binary_parser.rb', line 14

def peek
  if @bytes.empty?
    raise StandardError.new
  end
  @bytes[0]
end

#read(n) ⇒ Object



28
29
30
31
32
33
34
35
36
# File 'lib/binary-codec/serdes/binary_parser.rb', line 28

def read(n)
  if n > @bytes.length
    raise StandardError.new('End of byte stream reached')
  end

  slice = @bytes[0, n]
  skip(n)
  slice
end

#read_fieldObject



108
109
110
111
112
113
# File 'lib/binary-codec/serdes/binary_parser.rb', line 108

def read_field
  field_header = read_field_header
  field_name = @definitions.get_field_name_from_header(field_header)

  @definitions.get_field_instance(field_name)
end

#read_field_headerObject



86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'lib/binary-codec/serdes/binary_parser.rb', line 86

def read_field_header
  type = read_uint8
  nth = type & 15
  type >>= 4

  if type == 0
    type = read_uint8
    if type == 0 || type < 16
      raise StandardError.new("Cannot read FieldOrdinal, type_code #{type} out of range")
    end
  end

  if nth == 0
    nth = read_uint8
    if nth == 0 || nth < 16
      raise StandardError.new("Cannot read FieldOrdinal, field_code #{nth} out of range")
    end
  end

  FieldHeader.new(type: type, nth: nth) # (type << 16) | nth for read_field_ordinal
end

#read_field_value(field) ⇒ Object



123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
# File 'lib/binary-codec/serdes/binary_parser.rb', line 123

def read_field_value(field)
  type = SerializedType.get_type_by_name(field.type)

  if type.nil?
    raise StandardError.new("unsupported: (#{field.name}, #{field.type.name})")
  end

  size_hint = field.is_variable_length_encoded ? read_variable_length_length : nil
  value = type.from_parser(self, size_hint)

  if value.nil?
    raise StandardError.new("from_parser for (#{field.name}, #{field.type.name}) -> nil")
  end

  value
end

#read_type(type) ⇒ Object



115
116
117
# File 'lib/binary-codec/serdes/binary_parser.rb', line 115

def read_type(type)
  type.from_parser(self)
end

#read_uint16Object



49
50
51
# File 'lib/binary-codec/serdes/binary_parser.rb', line 49

def read_uint16
  read_uint_n(2)
end

#read_uint32Object



53
54
55
# File 'lib/binary-codec/serdes/binary_parser.rb', line 53

def read_uint32
  read_uint_n(4)
end

#read_uint8Object



45
46
47
# File 'lib/binary-codec/serdes/binary_parser.rb', line 45

def read_uint8
  read_uint_n(1)
end

#read_uint_n(n) ⇒ Object



38
39
40
41
42
43
# File 'lib/binary-codec/serdes/binary_parser.rb', line 38

def read_uint_n(n)
  if n <= 0 || n > 4
    raise StandardError.new('invalid n')
  end
  read(n).reduce(0) { |a, b| (a << 8) | b }
end

#read_variable_lengthObject



66
67
68
# File 'lib/binary-codec/serdes/binary_parser.rb', line 66

def read_variable_length
  read(read_variable_length_length)
end

#read_variable_length_lengthObject



70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/binary-codec/serdes/binary_parser.rb', line 70

def read_variable_length_length
  b1 = read_uint8
  if b1 <= 192
    b1
  elsif b1 <= 240
    b2 = read_uint8
    193 + (b1 - 193) * 256 + b2
  elsif b1 <= 254
    b2 = read_uint8
    b3 = read_uint8
    12481 + (b1 - 241) * 65536 + b2 * 256 + b3
  else
    raise StandardError.new('Invalid variable length indicator')
  end
end

#sizeObject



57
58
59
# File 'lib/binary-codec/serdes/binary_parser.rb', line 57

def size
  @bytes.length
end

#skip(n) ⇒ Object



21
22
23
24
25
26
# File 'lib/binary-codec/serdes/binary_parser.rb', line 21

def skip(n)
  if n > @bytes.length
    raise StandardError.new
  end
  @bytes = @bytes[n..-1]
end

#type_for_field(field) ⇒ Object



119
120
121
# File 'lib/binary-codec/serdes/binary_parser.rb', line 119

def type_for_field(field)
  field.associated_type
end