Index: third_party/gsutil/third_party/protorpc/protorpc/protobuf.py |
diff --git a/third_party/gsutil/third_party/protorpc/protorpc/protobuf.py b/third_party/gsutil/third_party/protorpc/protorpc/protobuf.py |
new file mode 100755 |
index 0000000000000000000000000000000000000000..18d0074a5130ff98a2dd7bf4c1027fb07620c82d |
--- /dev/null |
+++ b/third_party/gsutil/third_party/protorpc/protorpc/protobuf.py |
@@ -0,0 +1,359 @@ |
+#!/usr/bin/env python |
+# |
+# Copyright 2010 Google Inc. |
+# |
+# Licensed under the Apache License, Version 2.0 (the "License"); |
+# you may not use this file except in compliance with the License. |
+# You may obtain a copy of the License at |
+# |
+# http://www.apache.org/licenses/LICENSE-2.0 |
+# |
+# Unless required by applicable law or agreed to in writing, software |
+# distributed under the License is distributed on an "AS IS" BASIS, |
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
+# See the License for the specific language governing permissions and |
+# limitations under the License. |
+# |
+ |
+"""Protocol buffer support for message types. |
+ |
+For more details about protocol buffer encoding and decoding please see: |
+ |
+ http://code.google.com/apis/protocolbuffers/docs/encoding.html |
+ |
+Public Exceptions: |
+ DecodeError: Raised when a decode error occurs from incorrect protobuf format. |
+ |
+Public Functions: |
+ encode_message: Encodes a message in to a protocol buffer string. |
+ decode_message: Decode from a protocol buffer string to a message. |
+""" |
+import six |
+ |
+__author__ = 'rafek@google.com (Rafe Kaplan)' |
+ |
+ |
+import array |
+ |
+from . import message_types |
+from . import messages |
+from . import util |
+from .google_imports import ProtocolBuffer |
+ |
+ |
+__all__ = ['ALTERNATIVE_CONTENT_TYPES', |
+ 'CONTENT_TYPE', |
+ 'encode_message', |
+ 'decode_message', |
+ ] |
+ |
+CONTENT_TYPE = 'application/octet-stream' |
+ |
+ALTERNATIVE_CONTENT_TYPES = ['application/x-google-protobuf'] |
+ |
+ |
+class _Encoder(ProtocolBuffer.Encoder): |
+ """Extension of protocol buffer encoder. |
+ |
+ Original protocol buffer encoder does not have complete set of methods |
+ for handling required encoding. This class adds them. |
+ """ |
+ |
+ # TODO(rafek): Implement the missing encoding types. |
+ def no_encoding(self, value): |
+ """No encoding available for type. |
+ |
+ Args: |
+ value: Value to encode. |
+ |
+ Raises: |
+ NotImplementedError at all times. |
+ """ |
+ raise NotImplementedError() |
+ |
+ def encode_enum(self, value): |
+ """Encode an enum value. |
+ |
+ Args: |
+ value: Enum to encode. |
+ """ |
+ self.putVarInt32(value.number) |
+ |
+ def encode_message(self, value): |
+ """Encode a Message in to an embedded message. |
+ |
+ Args: |
+ value: Message instance to encode. |
+ """ |
+ self.putPrefixedString(encode_message(value)) |
+ |
+ |
+ def encode_unicode_string(self, value): |
+ """Helper to properly pb encode unicode strings to UTF-8. |
+ |
+ Args: |
+ value: String value to encode. |
+ """ |
+ if isinstance(value, six.text_type): |
+ value = value.encode('utf-8') |
+ self.putPrefixedString(value) |
+ |
+ |
+class _Decoder(ProtocolBuffer.Decoder): |
+ """Extension of protocol buffer decoder. |
+ |
+ Original protocol buffer decoder does not have complete set of methods |
+ for handling required decoding. This class adds them. |
+ """ |
+ |
+ # TODO(rafek): Implement the missing encoding types. |
+ def no_decoding(self): |
+ """No decoding available for type. |
+ |
+ Raises: |
+ NotImplementedError at all times. |
+ """ |
+ raise NotImplementedError() |
+ |
+ def decode_string(self): |
+ """Decode a unicode string. |
+ |
+ Returns: |
+ Next value in stream as a unicode string. |
+ """ |
+ return self.getPrefixedString().decode('UTF-8') |
+ |
+ def decode_boolean(self): |
+ """Decode a boolean value. |
+ |
+ Returns: |
+ Next value in stream as a boolean. |
+ """ |
+ return bool(self.getBoolean()) |
+ |
+ |
+# Number of bits used to describe a protocol buffer bits used for the variant. |
+_WIRE_TYPE_BITS = 3 |
+_WIRE_TYPE_MASK = 7 |
+ |
+ |
+# Maps variant to underlying wire type. Many variants map to same type. |
+_VARIANT_TO_WIRE_TYPE = { |
+ messages.Variant.DOUBLE: _Encoder.DOUBLE, |
+ messages.Variant.FLOAT: _Encoder.FLOAT, |
+ messages.Variant.INT64: _Encoder.NUMERIC, |
+ messages.Variant.UINT64: _Encoder.NUMERIC, |
+ messages.Variant.INT32: _Encoder.NUMERIC, |
+ messages.Variant.BOOL: _Encoder.NUMERIC, |
+ messages.Variant.STRING: _Encoder.STRING, |
+ messages.Variant.MESSAGE: _Encoder.STRING, |
+ messages.Variant.BYTES: _Encoder.STRING, |
+ messages.Variant.UINT32: _Encoder.NUMERIC, |
+ messages.Variant.ENUM: _Encoder.NUMERIC, |
+ messages.Variant.SINT32: _Encoder.NUMERIC, |
+ messages.Variant.SINT64: _Encoder.NUMERIC, |
+} |
+ |
+ |
+# Maps variant to encoder method. |
+_VARIANT_TO_ENCODER_MAP = { |
+ messages.Variant.DOUBLE: _Encoder.putDouble, |
+ messages.Variant.FLOAT: _Encoder.putFloat, |
+ messages.Variant.INT64: _Encoder.putVarInt64, |
+ messages.Variant.UINT64: _Encoder.putVarUint64, |
+ messages.Variant.INT32: _Encoder.putVarInt32, |
+ messages.Variant.BOOL: _Encoder.putBoolean, |
+ messages.Variant.STRING: _Encoder.encode_unicode_string, |
+ messages.Variant.MESSAGE: _Encoder.encode_message, |
+ messages.Variant.BYTES: _Encoder.encode_unicode_string, |
+ messages.Variant.UINT32: _Encoder.no_encoding, |
+ messages.Variant.ENUM: _Encoder.encode_enum, |
+ messages.Variant.SINT32: _Encoder.no_encoding, |
+ messages.Variant.SINT64: _Encoder.no_encoding, |
+} |
+ |
+ |
+# Basic wire format decoders. Used for reading unknown values. |
+_WIRE_TYPE_TO_DECODER_MAP = { |
+ _Encoder.NUMERIC: _Decoder.getVarInt64, |
+ _Encoder.DOUBLE: _Decoder.getDouble, |
+ _Encoder.STRING: _Decoder.getPrefixedString, |
+ _Encoder.FLOAT: _Decoder.getFloat, |
+} |
+ |
+ |
+# Map wire type to variant. Used to find a variant for unknown values. |
+_WIRE_TYPE_TO_VARIANT_MAP = { |
+ _Encoder.NUMERIC: messages.Variant.INT64, |
+ _Encoder.DOUBLE: messages.Variant.DOUBLE, |
+ _Encoder.STRING: messages.Variant.STRING, |
+ _Encoder.FLOAT: messages.Variant.FLOAT, |
+} |
+ |
+ |
+# Wire type to name mapping for error messages. |
+_WIRE_TYPE_NAME = { |
+ _Encoder.NUMERIC: 'NUMERIC', |
+ _Encoder.DOUBLE: 'DOUBLE', |
+ _Encoder.STRING: 'STRING', |
+ _Encoder.FLOAT: 'FLOAT', |
+} |
+ |
+ |
+# Maps variant to decoder method. |
+_VARIANT_TO_DECODER_MAP = { |
+ messages.Variant.DOUBLE: _Decoder.getDouble, |
+ messages.Variant.FLOAT: _Decoder.getFloat, |
+ messages.Variant.INT64: _Decoder.getVarInt64, |
+ messages.Variant.UINT64: _Decoder.getVarUint64, |
+ messages.Variant.INT32: _Decoder.getVarInt32, |
+ messages.Variant.BOOL: _Decoder.decode_boolean, |
+ messages.Variant.STRING: _Decoder.decode_string, |
+ messages.Variant.MESSAGE: _Decoder.getPrefixedString, |
+ messages.Variant.BYTES: _Decoder.getPrefixedString, |
+ messages.Variant.UINT32: _Decoder.no_decoding, |
+ messages.Variant.ENUM: _Decoder.getVarInt32, |
+ messages.Variant.SINT32: _Decoder.no_decoding, |
+ messages.Variant.SINT64: _Decoder.no_decoding, |
+} |
+ |
+ |
+def encode_message(message): |
+ """Encode Message instance to protocol buffer. |
+ |
+ Args: |
+ Message instance to encode in to protocol buffer. |
+ |
+ Returns: |
+ String encoding of Message instance in protocol buffer format. |
+ |
+ Raises: |
+ messages.ValidationError if message is not initialized. |
+ """ |
+ message.check_initialized() |
+ encoder = _Encoder() |
+ |
+ # Get all fields, from the known fields we parsed and the unknown fields |
+ # we saved. Note which ones were known, so we can process them differently. |
+ all_fields = [(field.number, field) for field in message.all_fields()] |
+ all_fields.extend((key, None) |
+ for key in message.all_unrecognized_fields() |
+ if isinstance(key, six.integer_types)) |
+ all_fields.sort() |
+ for field_num, field in all_fields: |
+ if field: |
+ # Known field. |
+ value = message.get_assigned_value(field.name) |
+ if value is None: |
+ continue |
+ variant = field.variant |
+ repeated = field.repeated |
+ else: |
+ # Unrecognized field. |
+ value, variant = message.get_unrecognized_field_info(field_num) |
+ if not isinstance(variant, messages.Variant): |
+ continue |
+ repeated = isinstance(value, (list, tuple)) |
+ |
+ tag = ((field_num << _WIRE_TYPE_BITS) | _VARIANT_TO_WIRE_TYPE[variant]) |
+ |
+ # Write value to wire. |
+ if repeated: |
+ values = value |
+ else: |
+ values = [value] |
+ for next in values: |
+ encoder.putVarInt32(tag) |
+ if isinstance(field, messages.MessageField): |
+ next = field.value_to_message(next) |
+ field_encoder = _VARIANT_TO_ENCODER_MAP[variant] |
+ field_encoder(encoder, next) |
+ |
+ return encoder.buffer().tostring() |
+ |
+ |
+def decode_message(message_type, encoded_message): |
+ """Decode protocol buffer to Message instance. |
+ |
+ Args: |
+ message_type: Message type to decode data to. |
+ encoded_message: Encoded version of message as string. |
+ |
+ Returns: |
+ Decoded instance of message_type. |
+ |
+ Raises: |
+ DecodeError if an error occurs during decoding, such as incompatible |
+ wire format for a field. |
+ messages.ValidationError if merged message is not initialized. |
+ """ |
+ message = message_type() |
+ message_array = array.array('B') |
+ message_array.fromstring(encoded_message) |
+ try: |
+ decoder = _Decoder(message_array, 0, len(message_array)) |
+ |
+ while decoder.avail() > 0: |
+ # Decode tag and variant information. |
+ encoded_tag = decoder.getVarInt32() |
+ tag = encoded_tag >> _WIRE_TYPE_BITS |
+ wire_type = encoded_tag & _WIRE_TYPE_MASK |
+ try: |
+ found_wire_type_decoder = _WIRE_TYPE_TO_DECODER_MAP[wire_type] |
+ except: |
+ raise messages.DecodeError('No such wire type %d' % wire_type) |
+ |
+ if tag < 1: |
+ raise messages.DecodeError('Invalid tag value %d' % tag) |
+ |
+ try: |
+ field = message.field_by_number(tag) |
+ except KeyError: |
+ # Unexpected tags are ok. |
+ field = None |
+ wire_type_decoder = found_wire_type_decoder |
+ else: |
+ expected_wire_type = _VARIANT_TO_WIRE_TYPE[field.variant] |
+ if expected_wire_type != wire_type: |
+ raise messages.DecodeError('Expected wire type %s but found %s' % ( |
+ _WIRE_TYPE_NAME[expected_wire_type], |
+ _WIRE_TYPE_NAME[wire_type])) |
+ |
+ wire_type_decoder = _VARIANT_TO_DECODER_MAP[field.variant] |
+ |
+ value = wire_type_decoder(decoder) |
+ |
+ # Save unknown fields and skip additional processing. |
+ if not field: |
+ # When saving this, save it under the tag number (which should |
+ # be unique), and set the variant and value so we know how to |
+ # interpret the value later. |
+ variant = _WIRE_TYPE_TO_VARIANT_MAP.get(wire_type) |
+ if variant: |
+ message.set_unrecognized_field(tag, value, variant) |
+ continue |
+ |
+ # Special case Enum and Message types. |
+ if isinstance(field, messages.EnumField): |
+ try: |
+ value = field.type(value) |
+ except TypeError: |
+ raise messages.DecodeError('Invalid enum value %s' % value) |
+ elif isinstance(field, messages.MessageField): |
+ value = decode_message(field.message_type, value) |
+ value = field.value_from_message(value) |
+ |
+ # Merge value in to message. |
+ if field.repeated: |
+ values = getattr(message, field.name) |
+ if values is None: |
+ setattr(message, field.name, [value]) |
+ else: |
+ values.append(value) |
+ else: |
+ setattr(message, field.name, value) |
+ except ProtocolBuffer.ProtocolBufferDecodeError as err: |
+ raise messages.DecodeError('Decoding error: %s' % str(err)) |
+ |
+ message.check_initialized() |
+ return message |