Initial Contribution
This commit is contained in:
commit
cf31fe9b4f
53 changed files with 11781 additions and 0 deletions
209
froofle/protobuf/internal/decoder.py
Normal file
209
froofle/protobuf/internal/decoder.py
Normal file
|
@ -0,0 +1,209 @@
|
|||
# Protocol Buffers - Google's data interchange format
|
||||
# Copyright 2008 Google Inc. All rights reserved.
|
||||
# http://code.google.com/p/protobuf/
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions are
|
||||
# met:
|
||||
#
|
||||
# * Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# * Redistributions in binary form must reproduce the above
|
||||
# copyright notice, this list of conditions and the following disclaimer
|
||||
# in the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# * Neither the name of Google Inc. nor the names of its
|
||||
# contributors may be used to endorse or promote products derived from
|
||||
# this software without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
|
||||
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
|
||||
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
|
||||
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
|
||||
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
"""Class for decoding protocol buffer primitives.
|
||||
|
||||
Contains the logic for decoding every logical protocol field type
|
||||
from one of the 5 physical wire types.
|
||||
"""
|
||||
|
||||
__author__ = 'robinson@google.com (Will Robinson)'
|
||||
|
||||
import struct
|
||||
from froofle.protobuf import message
|
||||
from froofle.protobuf.internal import input_stream
|
||||
from froofle.protobuf.internal import wire_format
|
||||
|
||||
|
||||
|
||||
# Note that much of this code is ported from //net/proto/ProtocolBuffer, and
|
||||
# that the interface is strongly inspired by WireFormat from the C++ proto2
|
||||
# implementation.
|
||||
|
||||
|
||||
class Decoder(object):
|
||||
|
||||
"""Decodes logical protocol buffer fields from the wire."""
|
||||
|
||||
def __init__(self, s):
|
||||
"""Initializes the decoder to read from s.
|
||||
|
||||
Args:
|
||||
s: An immutable sequence of bytes, which must be accessible
|
||||
via the Python buffer() primitive (i.e., buffer(s)).
|
||||
"""
|
||||
self._stream = input_stream.InputStream(s)
|
||||
|
||||
def EndOfStream(self):
|
||||
"""Returns true iff we've reached the end of the bytes we're reading."""
|
||||
return self._stream.EndOfStream()
|
||||
|
||||
def Position(self):
|
||||
"""Returns the 0-indexed position in |s|."""
|
||||
return self._stream.Position()
|
||||
|
||||
def ReadFieldNumberAndWireType(self):
|
||||
"""Reads a tag from the wire. Returns a (field_number, wire_type) pair."""
|
||||
tag_and_type = self.ReadUInt32()
|
||||
return wire_format.UnpackTag(tag_and_type)
|
||||
|
||||
def SkipBytes(self, bytes):
|
||||
"""Skips the specified number of bytes on the wire."""
|
||||
self._stream.SkipBytes(bytes)
|
||||
|
||||
# Note that the Read*() methods below are not exactly symmetrical with the
|
||||
# corresponding Encoder.Append*() methods. Those Encoder methods first
|
||||
# encode a tag, but the Read*() methods below assume that the tag has already
|
||||
# been read, and that the client wishes to read a field of the specified type
|
||||
# starting at the current position.
|
||||
|
||||
def ReadInt32(self):
|
||||
"""Reads and returns a signed, varint-encoded, 32-bit integer."""
|
||||
return self._stream.ReadVarint32()
|
||||
|
||||
def ReadInt64(self):
|
||||
"""Reads and returns a signed, varint-encoded, 64-bit integer."""
|
||||
return self._stream.ReadVarint64()
|
||||
|
||||
def ReadUInt32(self):
|
||||
"""Reads and returns an signed, varint-encoded, 32-bit integer."""
|
||||
return self._stream.ReadVarUInt32()
|
||||
|
||||
def ReadUInt64(self):
|
||||
"""Reads and returns an signed, varint-encoded,64-bit integer."""
|
||||
return self._stream.ReadVarUInt64()
|
||||
|
||||
def ReadSInt32(self):
|
||||
"""Reads and returns a signed, zigzag-encoded, varint-encoded,
|
||||
32-bit integer."""
|
||||
return wire_format.ZigZagDecode(self._stream.ReadVarUInt32())
|
||||
|
||||
def ReadSInt64(self):
|
||||
"""Reads and returns a signed, zigzag-encoded, varint-encoded,
|
||||
64-bit integer."""
|
||||
return wire_format.ZigZagDecode(self._stream.ReadVarUInt64())
|
||||
|
||||
def ReadFixed32(self):
|
||||
"""Reads and returns an unsigned, fixed-width, 32-bit integer."""
|
||||
return self._stream.ReadLittleEndian32()
|
||||
|
||||
def ReadFixed64(self):
|
||||
"""Reads and returns an unsigned, fixed-width, 64-bit integer."""
|
||||
return self._stream.ReadLittleEndian64()
|
||||
|
||||
def ReadSFixed32(self):
|
||||
"""Reads and returns a signed, fixed-width, 32-bit integer."""
|
||||
value = self._stream.ReadLittleEndian32()
|
||||
if value >= (1 << 31):
|
||||
value -= (1 << 32)
|
||||
return value
|
||||
|
||||
def ReadSFixed64(self):
|
||||
"""Reads and returns a signed, fixed-width, 64-bit integer."""
|
||||
value = self._stream.ReadLittleEndian64()
|
||||
if value >= (1 << 63):
|
||||
value -= (1 << 64)
|
||||
return value
|
||||
|
||||
def ReadFloat(self):
|
||||
"""Reads and returns a 4-byte floating-point number."""
|
||||
serialized = self._stream.ReadBytes(4)
|
||||
return struct.unpack('f', serialized)[0]
|
||||
|
||||
def ReadDouble(self):
|
||||
"""Reads and returns an 8-byte floating-point number."""
|
||||
serialized = self._stream.ReadBytes(8)
|
||||
return struct.unpack('d', serialized)[0]
|
||||
|
||||
def ReadBool(self):
|
||||
"""Reads and returns a bool."""
|
||||
i = self._stream.ReadVarUInt32()
|
||||
return bool(i)
|
||||
|
||||
def ReadEnum(self):
|
||||
"""Reads and returns an enum value."""
|
||||
return self._stream.ReadVarUInt32()
|
||||
|
||||
def ReadString(self):
|
||||
"""Reads and returns a length-delimited string."""
|
||||
bytes = self.ReadBytes()
|
||||
return unicode(bytes, 'utf-8')
|
||||
|
||||
def ReadBytes(self):
|
||||
"""Reads and returns a length-delimited byte sequence."""
|
||||
length = self._stream.ReadVarUInt32()
|
||||
return self._stream.ReadBytes(length)
|
||||
|
||||
def ReadMessageInto(self, msg):
|
||||
"""Calls msg.MergeFromString() to merge
|
||||
length-delimited serialized message data into |msg|.
|
||||
|
||||
REQUIRES: The decoder must be positioned at the serialized "length"
|
||||
prefix to a length-delmiited serialized message.
|
||||
|
||||
POSTCONDITION: The decoder is positioned just after the
|
||||
serialized message, and we have merged those serialized
|
||||
contents into |msg|.
|
||||
"""
|
||||
length = self._stream.ReadVarUInt32()
|
||||
sub_buffer = self._stream.GetSubBuffer(length)
|
||||
num_bytes_used = msg.MergeFromString(sub_buffer)
|
||||
if num_bytes_used != length:
|
||||
raise message.DecodeError(
|
||||
'Submessage told to deserialize from %d-byte encoding, '
|
||||
'but used only %d bytes' % (length, num_bytes_used))
|
||||
self._stream.SkipBytes(num_bytes_used)
|
||||
|
||||
def ReadGroupInto(self, expected_field_number, group):
|
||||
"""Calls group.MergeFromString() to merge
|
||||
END_GROUP-delimited serialized message data into |group|.
|
||||
We'll raise an exception if we don't find an END_GROUP
|
||||
tag immediately after the serialized message contents.
|
||||
|
||||
REQUIRES: The decoder is positioned just after the START_GROUP
|
||||
tag for this group.
|
||||
|
||||
POSTCONDITION: The decoder is positioned just after the
|
||||
END_GROUP tag for this group, and we have merged
|
||||
the contents of the group into |group|.
|
||||
"""
|
||||
sub_buffer = self._stream.GetSubBuffer() # No a priori length limit.
|
||||
num_bytes_used = group.MergeFromString(sub_buffer)
|
||||
if num_bytes_used < 0:
|
||||
raise message.DecodeError('Group message reported negative bytes read.')
|
||||
self._stream.SkipBytes(num_bytes_used)
|
||||
field_number, field_type = self.ReadFieldNumberAndWireType()
|
||||
if field_type != wire_format.WIRETYPE_END_GROUP:
|
||||
raise message.DecodeError('Group message did not end with an END_GROUP.')
|
||||
if field_number != expected_field_number:
|
||||
raise message.DecodeError('END_GROUP tag had field '
|
||||
'number %d, was expecting field number %d' % (
|
||||
field_number, expected_field_number))
|
||||
# We're now positioned just after the END_GROUP tag. Perfect.
|
Loading…
Add table
Add a link
Reference in a new issue