Module: ProtocolBuffers::Decoder
- Defined in:
- lib/protocol_buffers/runtime/decoder.rb
Overview
:nodoc: all
Class Method Summary collapse
Class Method Details
.decode(io, message) ⇒ Object
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 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 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 |
# File 'lib/protocol_buffers/runtime/decoder.rb', line 8 def self.decode(io, ) fields = .fields until io.eof? tag_int = Varint.decode(io) tag = tag_int >> 3 wire_type = tag_int & 0b111 field = fields[tag] if field && wire_type != field.wire_type raise(DecodeError, "incorrect wire type for tag: #{field.tag}, expected #{field.wire_type} but got #{wire_type}\n#{field.inspect}") end # replacing const lookups with hard-coded ints removed an entire 10% # from an earlier decoding benchmark. these values can't change without # breaking the protocol anyway, so we decided it was worth it. case wire_type when 0 # VARINT value = Varint.decode(io) when 1 # FIXED64 value = io.read(8) when 2 # LENGTH_DELIMITED length = Varint.decode(io) value = LimitedIO.new(io, length) when 5 # FIXED32 value = io.read(4) when 3, 4 # deprecated START_GROUP/END_GROUP types raise(DecodeError, "groups are deprecated and unsupported") else raise(DecodeError, "unknown wire type: #{wire_type}") end if field begin deserialized = field.deserialize(value) # merge_field handles repeated field logic .merge_field(tag, deserialized, field) rescue ArgumentError # for enum fields, treat bad values as unknown fields if field.is_a?(Field::EnumField) field = nil else raise end end end unless field # ignore unknown fields, pass them on when re-serializing this message # special handling -- if it's a LENGTH_DELIMITED field, we need to # actually read the IO so that extra bytes aren't left on the wire value = value.read if wire_type == 2 # LENGTH_DELIMITED .remember_unknown_field(tag_int, value) end end unless .valid? raise(DecodeError, "invalid message") end return rescue TypeError, ArgumentError raise(DecodeError, "error parsing message") end |