Module: Protobug::BinaryEncoding
- Defined in:
- lib/protobug/binary_encoding.rb
Class Method Summary collapse
- .decode_length(binary) ⇒ Object
- .decode_varint(binary) ⇒ Object
- .decode_zigzag(size, value) ⇒ Object
- .encode_length(contents, outbuf) ⇒ Object
- .encode_varint(value, outbuf) ⇒ Object
- .encode_zigzag(size, value, outbuf) ⇒ Object
- .read_field_value(binary, wire_type) ⇒ Object
Class Method Details
.decode_length(binary) ⇒ Object
63 64 65 66 67 68 69 |
# File 'lib/protobug/binary_encoding.rb', line 63 def decode_length(binary) length = decode_varint(binary) || raise(EOFError, "unexpected EOF") string = binary.read(length) || raise(EOFError, "unexpected EOF") raise EOFError, "expected #{length} bytes, got #{string.bytesize}" unless string.bytesize == length string end |
.decode_varint(binary) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 |
# File 'lib/protobug/binary_encoding.rb', line 46 def decode_varint(binary) byte = binary.getbyte return unless byte value = 0 bl = 0 loop do raise DecodeError, "varint too large" if bl > 63 return value if byte.nil? return value | (byte << bl) if (byte & 0b1000_0000).zero? # no continuation bit set value |= ((byte & 0b0111_1111) << bl) bl += 7 byte = binary.getbyte || raise(EOFError, "unexpected EOF") end end |
.decode_zigzag(size, value) ⇒ Object
71 72 73 74 75 76 77 78 79 80 81 82 83 |
# File 'lib/protobug/binary_encoding.rb', line 71 def decode_zigzag(size, value) negative = value & 1 == 1 value %= 2**size value >>= 1 value = -value - 1 if negative unless value.bit_length <= size raise DecodeError, "bitlength too large for #{size}-bit integer: #{value.bit_length}" end value end |
.encode_length(contents, outbuf) ⇒ Object
41 42 43 44 |
# File 'lib/protobug/binary_encoding.rb', line 41 def encode_length(contents, outbuf) encode_varint contents.bytesize, outbuf outbuf << contents end |
.encode_varint(value, outbuf) ⇒ Object
9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# File 'lib/protobug/binary_encoding.rb', line 9 def encode_varint(value, outbuf) raise EncodeError, "expected integer, got #{value.inspect}" unless value.is_a? Integer raise RangeError, "expected 64-bit integer" if value > (2**64) - 1 || value < -2**63 negative = value.negative? value = (2**64) + value if negative out = [] loop do if value.bit_length > 7 out << (0b1000_0000 | (value & 0b0111_1111)) value >>= 7 else out << (value & 0b0111_1111) break end end out.pack("c*", buffer: outbuf) end |
.encode_zigzag(size, value, outbuf) ⇒ Object
28 29 30 31 32 33 34 35 36 37 38 39 |
# File 'lib/protobug/binary_encoding.rb', line 28 def encode_zigzag(size, value, outbuf) raise EncodeError, "expected integer, got #{value.inspect}" unless value.is_a? Integer unless value.bit_length <= size raise EncodeError, "bitlength too large for #{size}-bit integer: #{value.bit_length}" end encoded = 2 * value.abs encoded -= 1 if value.negative? encode_varint encoded, outbuf end |
.read_field_value(binary, wire_type) ⇒ Object
85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 |
# File 'lib/protobug/binary_encoding.rb', line 85 def read_field_value(binary, wire_type) case wire_type when 0 decode_varint(binary) || raise(EOFError, "unexpected EOF") when 1 value = binary.read(8) raise EOFError, "unexpected EOF" if value&.bytesize != 8 value when 2 decode_length(binary) when 3, 4 raise UnsupportedFeatureError.new(:group, "reading groups from binary protos (in #{self})") when 5 value = binary.read(4) raise EOFError, "unexpected EOF" if value&.bytesize != 4 value else raise DecodeError, "unknown wire_type: #{wire_type}" end end |