Class: BinaryCodec::BinaryParser
- Inherits:
-
Object
- Object
- BinaryCodec::BinaryParser
- Defined in:
- lib/binary-codec/serdes/binary_parser.rb
Instance Attribute Summary collapse
-
#definitions ⇒ Object
readonly
Returns the value of attribute definitions.
Instance Method Summary collapse
-
#end?(custom_end = nil) ⇒ Boolean
Checks if the end of the stream has been reached.
-
#initialize(hex_bytes = '') ⇒ BinaryParser
constructor
A new instance of BinaryParser.
-
#peek ⇒ Integer
Returns the first byte in the stream without consuming it.
-
#read(n) ⇒ Array<Integer>
Reads n bytes from the stream.
-
#read_field ⇒ FieldInstance
Reads a field instance from the stream.
-
#read_field_header ⇒ FieldHeader
Reads a field header from the stream.
-
#read_field_value(field) ⇒ SerializedType
Reads the value of a specific field from the stream.
-
#read_type(type) ⇒ SerializedType
Reads a value of the specified type from the stream.
-
#read_uint16 ⇒ Integer
Reads a 2-byte unsigned integer.
-
#read_uint32 ⇒ Integer
Reads a 4-byte unsigned integer.
-
#read_uint8 ⇒ Integer
Reads a 1-byte unsigned integer.
-
#read_uint_n(n) ⇒ Integer
Reads n bytes and converts them to an unsigned integer.
-
#read_variable_length ⇒ Array<Integer>
Reads variable length data from the stream.
-
#read_variable_length_length ⇒ Integer
Reads the length of a variable length data segment.
-
#size ⇒ Integer
Returns the number of bytes remaining in the stream.
-
#skip(n) ⇒ Object
Consumes n bytes from the stream.
-
#type_for_field(field) ⇒ Class
Returns the associated type for a given field.
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
#definitions ⇒ Object (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
Checks if the end of the stream has been reached.
82 83 84 85 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 82 def end?(custom_end = nil) length = @bytes.length length == 0 || (!custom_end.nil? && length <= custom_end) end |
#peek ⇒ Integer
Returns the first byte in the stream without consuming it.
16 17 18 19 20 21 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 16 def peek if @bytes.empty? raise StandardError.new end @bytes[0] end |
#read(n) ⇒ Array<Integer>
Reads n bytes from the stream.
35 36 37 38 39 40 41 42 43 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 35 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_field ⇒ FieldInstance
Reads a field instance from the stream.
137 138 139 140 141 142 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 137 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_header ⇒ FieldHeader
Reads a field header from the stream.
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 113 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) ⇒ SerializedType
Reads the value of a specific field from the stream.
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 161 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) ⇒ SerializedType
Reads a value of the specified type from the stream.
147 148 149 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 147 def read_type(type) type.from_parser(self) end |
#read_uint16 ⇒ Integer
Reads a 2-byte unsigned integer.
63 64 65 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 63 def read_uint16 read_uint_n(2) end |
#read_uint32 ⇒ Integer
Reads a 4-byte unsigned integer.
69 70 71 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 69 def read_uint32 read_uint_n(4) end |
#read_uint8 ⇒ Integer
Reads a 1-byte unsigned integer.
57 58 59 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 57 def read_uint8 read_uint_n(1) end |
#read_uint_n(n) ⇒ Integer
Reads n bytes and converts them to an unsigned integer.
48 49 50 51 52 53 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 48 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_length ⇒ Array<Integer>
Reads variable length data from the stream.
89 90 91 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 89 def read_variable_length read(read_variable_length_length) end |
#read_variable_length_length ⇒ Integer
Reads the length of a variable length data segment.
95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 95 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 |
#size ⇒ Integer
Returns the number of bytes remaining in the stream.
75 76 77 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 75 def size @bytes.length end |
#skip(n) ⇒ Object
Consumes n bytes from the stream.
25 26 27 28 29 30 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 25 def skip(n) if n > @bytes.length raise StandardError.new end @bytes = @bytes[n..-1] end |
#type_for_field(field) ⇒ Class
Returns the associated type for a given field.
154 155 156 |
# File 'lib/binary-codec/serdes/binary_parser.rb', line 154 def type_for_field(field) field.associated_type end |