# 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.
