Index: third_party/protobuf/python/google/protobuf/internal/encoder.py |
diff --git a/third_party/protobuf/python/google/protobuf/internal/encoder.py b/third_party/protobuf/python/google/protobuf/internal/encoder.py |
index 777975e82e042b277be6ff6b1dae3b4f5cf6fa57..48ef2df31c21dae7cb5b8c813a38613da63a22e6 100755 |
--- a/third_party/protobuf/python/google/protobuf/internal/encoder.py |
+++ b/third_party/protobuf/python/google/protobuf/internal/encoder.py |
@@ -1,6 +1,6 @@ |
# Protocol Buffers - Google's data interchange format |
# Copyright 2008 Google Inc. All rights reserved. |
-# http://code.google.com/p/protobuf/ |
+# https://developers.google.com/protocol-buffers/ |
# |
# Redistribution and use in source and binary forms, with or without |
# modification, are permitted provided that the following conditions are |
@@ -41,7 +41,7 @@ FieldDescriptor) we construct two functions: a "sizer" and an "encoder". The |
sizer takes a value of this field's type and computes its byte size. The |
encoder takes a writer function and a value. It encodes the value into byte |
strings and invokes the writer function to write those strings. Typically the |
-writer function is the write() method of a cStringIO. |
+writer function is the write() method of a BytesIO. |
We try to do as much work as possible when constructing the writer and the |
sizer rather than when calling them. In particular: |
@@ -67,6 +67,9 @@ sizer rather than when calling them. In particular: |
__author__ = 'kenton@google.com (Kenton Varda)' |
import struct |
+ |
+import six |
+ |
from google.protobuf.internal import wire_format |
@@ -308,7 +311,7 @@ def MessageSizer(field_number, is_repeated, is_packed): |
# -------------------------------------------------------------------- |
-# MessageSet is special. |
+# MessageSet is special: it needs custom logic to compute its size properly. |
def MessageSetItemSizer(field_number): |
@@ -333,6 +336,32 @@ def MessageSetItemSizer(field_number): |
return FieldSize |
+# -------------------------------------------------------------------- |
+# Map is special: it needs custom logic to compute its size properly. |
+ |
+ |
+def MapSizer(field_descriptor): |
+ """Returns a sizer for a map field.""" |
+ |
+ # Can't look at field_descriptor.message_type._concrete_class because it may |
+ # not have been initialized yet. |
+ message_type = field_descriptor.message_type |
+ message_sizer = MessageSizer(field_descriptor.number, False, False) |
+ |
+ def FieldSize(map_value): |
+ total = 0 |
+ for key in map_value: |
+ value = map_value[key] |
+ # It's wasteful to create the messages and throw them away one second |
+ # later since we'll do the same for the actual encode. But there's not an |
+ # obvious way to avoid this within the current design without tons of code |
+ # duplication. |
+ entry_msg = message_type._concrete_class(key=key, value=value) |
+ total += message_sizer(entry_msg) |
+ return total |
+ |
+ return FieldSize |
+ |
# ==================================================================== |
# Encoders! |
@@ -340,15 +369,14 @@ def MessageSetItemSizer(field_number): |
def _VarintEncoder(): |
"""Return an encoder for a basic varint value (does not include tag).""" |
- local_chr = chr |
def EncodeVarint(write, value): |
bits = value & 0x7f |
value >>= 7 |
while value: |
- write(local_chr(0x80|bits)) |
+ write(six.int2byte(0x80|bits)) |
bits = value & 0x7f |
value >>= 7 |
- return write(local_chr(bits)) |
+ return write(six.int2byte(bits)) |
return EncodeVarint |
@@ -357,17 +385,16 @@ def _SignedVarintEncoder(): |
"""Return an encoder for a basic signed varint value (does not include |
tag).""" |
- local_chr = chr |
def EncodeSignedVarint(write, value): |
if value < 0: |
value += (1 << 64) |
bits = value & 0x7f |
value >>= 7 |
while value: |
- write(local_chr(0x80|bits)) |
+ write(six.int2byte(0x80|bits)) |
bits = value & 0x7f |
value >>= 7 |
- return write(local_chr(bits)) |
+ return write(six.int2byte(bits)) |
return EncodeSignedVarint |
@@ -382,7 +409,7 @@ def _VarintBytes(value): |
pieces = [] |
_EncodeVarint(pieces.append, value) |
- return "".join(pieces) |
+ return b"".join(pieces) |
def TagBytes(field_number, wire_type): |
@@ -525,21 +552,21 @@ def _FloatingPointEncoder(wire_type, format): |
def EncodeNonFiniteOrRaise(write, value): |
# Remember that the serialized form uses little-endian byte order. |
if value == _POS_INF: |
- write('\x00\x00\x80\x7F') |
+ write(b'\x00\x00\x80\x7F') |
elif value == _NEG_INF: |
- write('\x00\x00\x80\xFF') |
+ write(b'\x00\x00\x80\xFF') |
elif value != value: # NaN |
- write('\x00\x00\xC0\x7F') |
+ write(b'\x00\x00\xC0\x7F') |
else: |
raise |
elif value_size == 8: |
def EncodeNonFiniteOrRaise(write, value): |
if value == _POS_INF: |
- write('\x00\x00\x00\x00\x00\x00\xF0\x7F') |
+ write(b'\x00\x00\x00\x00\x00\x00\xF0\x7F') |
elif value == _NEG_INF: |
- write('\x00\x00\x00\x00\x00\x00\xF0\xFF') |
+ write(b'\x00\x00\x00\x00\x00\x00\xF0\xFF') |
elif value != value: # NaN |
- write('\x00\x00\x00\x00\x00\x00\xF8\x7F') |
+ write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F') |
else: |
raise |
else: |
@@ -615,8 +642,8 @@ DoubleEncoder = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED64, '<d') |
def BoolEncoder(field_number, is_repeated, is_packed): |
"""Returns an encoder for a boolean field.""" |
- false_byte = chr(0) |
- true_byte = chr(1) |
+ false_byte = b'\x00' |
+ true_byte = b'\x01' |
if is_packed: |
tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) |
local_EncodeVarint = _EncodeVarint |
@@ -752,7 +779,7 @@ def MessageSetItemEncoder(field_number): |
} |
} |
""" |
- start_bytes = "".join([ |
+ start_bytes = b"".join([ |
TagBytes(1, wire_format.WIRETYPE_START_GROUP), |
TagBytes(2, wire_format.WIRETYPE_VARINT), |
_VarintBytes(field_number), |
@@ -767,3 +794,30 @@ def MessageSetItemEncoder(field_number): |
return write(end_bytes) |
return EncodeField |
+ |
+ |
+# -------------------------------------------------------------------- |
+# As before, Map is special. |
+ |
+ |
+def MapEncoder(field_descriptor): |
+ """Encoder for extensions of MessageSet. |
+ |
+ Maps always have a wire format like this: |
+ message MapEntry { |
+ key_type key = 1; |
+ value_type value = 2; |
+ } |
+ repeated MapEntry map = N; |
+ """ |
+ # Can't look at field_descriptor.message_type._concrete_class because it may |
+ # not have been initialized yet. |
+ message_type = field_descriptor.message_type |
+ encode_message = MessageEncoder(field_descriptor.number, False, False) |
+ |
+ def EncodeField(write, value): |
+ for key in value: |
+ entry_msg = message_type._concrete_class(key=key, value=value[key]) |
+ encode_message(write, entry_msg) |
+ |
+ return EncodeField |