1# Protocol Buffers - Google's data interchange format 2# Copyright 2008 Google Inc. All rights reserved. 3# https://developers.google.com/protocol-buffers/ 4# 5# Redistribution and use in source and binary forms, with or without 6# modification, are permitted provided that the following conditions are 7# met: 8# 9# * Redistributions of source code must retain the above copyright 10# notice, this list of conditions and the following disclaimer. 11# * Redistributions in binary form must reproduce the above 12# copyright notice, this list of conditions and the following disclaimer 13# in the documentation and/or other materials provided with the 14# distribution. 15# * Neither the name of Google Inc. nor the names of its 16# contributors may be used to endorse or promote products derived from 17# this software without specific prior written permission. 18# 19# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 20# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 21# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 22# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 23# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 24# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 25# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 26# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 27# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 28# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 29# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 30 31#PY25 compatible for GAE. 32# 33# Copyright 2009 Google Inc. All Rights Reserved. 34 35"""Code for encoding protocol message primitives. 36 37Contains the logic for encoding every logical protocol field type 38into one of the 5 physical wire types. 39 40This code is designed to push the Python interpreter's performance to the 41limits. 42 43The basic idea is that at startup time, for every field (i.e. every 44FieldDescriptor) we construct two functions: a "sizer" and an "encoder". The 45sizer takes a value of this field's type and computes its byte size. The 46encoder takes a writer function and a value. It encodes the value into byte 47strings and invokes the writer function to write those strings. Typically the 48writer function is the write() method of a cStringIO. 49 50We try to do as much work as possible when constructing the writer and the 51sizer rather than when calling them. In particular: 52* We copy any needed global functions to local variables, so that we do not need 53 to do costly global table lookups at runtime. 54* Similarly, we try to do any attribute lookups at startup time if possible. 55* Every field's tag is encoded to bytes at startup, since it can't change at 56 runtime. 57* Whatever component of the field size we can compute at startup, we do. 58* We *avoid* sharing code if doing so would make the code slower and not sharing 59 does not burden us too much. For example, encoders for repeated fields do 60 not just call the encoders for singular fields in a loop because this would 61 add an extra function call overhead for every loop iteration; instead, we 62 manually inline the single-value encoder into the loop. 63* If a Python function lacks a return statement, Python actually generates 64 instructions to pop the result of the last statement off the stack, push 65 None onto the stack, and then return that. If we really don't care what 66 value is returned, then we can save two instructions by returning the 67 result of the last statement. It looks funny but it helps. 68* We assume that type and bounds checking has happened at a higher level. 69""" 70 71__author__ = 'kenton@google.com (Kenton Varda)' 72 73import struct 74import sys ##PY25 75_PY2 = sys.version_info[0] < 3 ##PY25 76from google.protobuf.internal import wire_format 77 78 79# This will overflow and thus become IEEE-754 "infinity". We would use 80# "float('inf')" but it doesn't work on Windows pre-Python-2.6. 81_POS_INF = 1e10000 82_NEG_INF = -_POS_INF 83 84 85def _VarintSize(value): 86 """Compute the size of a varint value.""" 87 if value <= 0x7f: return 1 88 if value <= 0x3fff: return 2 89 if value <= 0x1fffff: return 3 90 if value <= 0xfffffff: return 4 91 if value <= 0x7ffffffff: return 5 92 if value <= 0x3ffffffffff: return 6 93 if value <= 0x1ffffffffffff: return 7 94 if value <= 0xffffffffffffff: return 8 95 if value <= 0x7fffffffffffffff: return 9 96 return 10 97 98 99def _SignedVarintSize(value): 100 """Compute the size of a signed varint value.""" 101 if value < 0: return 10 102 if value <= 0x7f: return 1 103 if value <= 0x3fff: return 2 104 if value <= 0x1fffff: return 3 105 if value <= 0xfffffff: return 4 106 if value <= 0x7ffffffff: return 5 107 if value <= 0x3ffffffffff: return 6 108 if value <= 0x1ffffffffffff: return 7 109 if value <= 0xffffffffffffff: return 8 110 if value <= 0x7fffffffffffffff: return 9 111 return 10 112 113 114def _TagSize(field_number): 115 """Returns the number of bytes required to serialize a tag with this field 116 number.""" 117 # Just pass in type 0, since the type won't affect the tag+type size. 118 return _VarintSize(wire_format.PackTag(field_number, 0)) 119 120 121# -------------------------------------------------------------------- 122# In this section we define some generic sizers. Each of these functions 123# takes parameters specific to a particular field type, e.g. int32 or fixed64. 124# It returns another function which in turn takes parameters specific to a 125# particular field, e.g. the field number and whether it is repeated or packed. 126# Look at the next section to see how these are used. 127 128 129def _SimpleSizer(compute_value_size): 130 """A sizer which uses the function compute_value_size to compute the size of 131 each value. Typically compute_value_size is _VarintSize.""" 132 133 def SpecificSizer(field_number, is_repeated, is_packed): 134 tag_size = _TagSize(field_number) 135 if is_packed: 136 local_VarintSize = _VarintSize 137 def PackedFieldSize(value): 138 result = 0 139 for element in value: 140 result += compute_value_size(element) 141 return result + local_VarintSize(result) + tag_size 142 return PackedFieldSize 143 elif is_repeated: 144 def RepeatedFieldSize(value): 145 result = tag_size * len(value) 146 for element in value: 147 result += compute_value_size(element) 148 return result 149 return RepeatedFieldSize 150 else: 151 def FieldSize(value): 152 return tag_size + compute_value_size(value) 153 return FieldSize 154 155 return SpecificSizer 156 157 158def _ModifiedSizer(compute_value_size, modify_value): 159 """Like SimpleSizer, but modify_value is invoked on each value before it is 160 passed to compute_value_size. modify_value is typically ZigZagEncode.""" 161 162 def SpecificSizer(field_number, is_repeated, is_packed): 163 tag_size = _TagSize(field_number) 164 if is_packed: 165 local_VarintSize = _VarintSize 166 def PackedFieldSize(value): 167 result = 0 168 for element in value: 169 result += compute_value_size(modify_value(element)) 170 return result + local_VarintSize(result) + tag_size 171 return PackedFieldSize 172 elif is_repeated: 173 def RepeatedFieldSize(value): 174 result = tag_size * len(value) 175 for element in value: 176 result += compute_value_size(modify_value(element)) 177 return result 178 return RepeatedFieldSize 179 else: 180 def FieldSize(value): 181 return tag_size + compute_value_size(modify_value(value)) 182 return FieldSize 183 184 return SpecificSizer 185 186 187def _FixedSizer(value_size): 188 """Like _SimpleSizer except for a fixed-size field. The input is the size 189 of one value.""" 190 191 def SpecificSizer(field_number, is_repeated, is_packed): 192 tag_size = _TagSize(field_number) 193 if is_packed: 194 local_VarintSize = _VarintSize 195 def PackedFieldSize(value): 196 result = len(value) * value_size 197 return result + local_VarintSize(result) + tag_size 198 return PackedFieldSize 199 elif is_repeated: 200 element_size = value_size + tag_size 201 def RepeatedFieldSize(value): 202 return len(value) * element_size 203 return RepeatedFieldSize 204 else: 205 field_size = value_size + tag_size 206 def FieldSize(value): 207 return field_size 208 return FieldSize 209 210 return SpecificSizer 211 212 213# ==================================================================== 214# Here we declare a sizer constructor for each field type. Each "sizer 215# constructor" is a function that takes (field_number, is_repeated, is_packed) 216# as parameters and returns a sizer, which in turn takes a field value as 217# a parameter and returns its encoded size. 218 219 220Int32Sizer = Int64Sizer = EnumSizer = _SimpleSizer(_SignedVarintSize) 221 222UInt32Sizer = UInt64Sizer = _SimpleSizer(_VarintSize) 223 224SInt32Sizer = SInt64Sizer = _ModifiedSizer( 225 _SignedVarintSize, wire_format.ZigZagEncode) 226 227Fixed32Sizer = SFixed32Sizer = FloatSizer = _FixedSizer(4) 228Fixed64Sizer = SFixed64Sizer = DoubleSizer = _FixedSizer(8) 229 230BoolSizer = _FixedSizer(1) 231 232 233def StringSizer(field_number, is_repeated, is_packed): 234 """Returns a sizer for a string field.""" 235 236 tag_size = _TagSize(field_number) 237 local_VarintSize = _VarintSize 238 local_len = len 239 assert not is_packed 240 if is_repeated: 241 def RepeatedFieldSize(value): 242 result = tag_size * len(value) 243 for element in value: 244 l = local_len(element.encode('utf-8')) 245 result += local_VarintSize(l) + l 246 return result 247 return RepeatedFieldSize 248 else: 249 def FieldSize(value): 250 l = local_len(value.encode('utf-8')) 251 return tag_size + local_VarintSize(l) + l 252 return FieldSize 253 254 255def BytesSizer(field_number, is_repeated, is_packed): 256 """Returns a sizer for a bytes field.""" 257 258 tag_size = _TagSize(field_number) 259 local_VarintSize = _VarintSize 260 local_len = len 261 assert not is_packed 262 if is_repeated: 263 def RepeatedFieldSize(value): 264 result = tag_size * len(value) 265 for element in value: 266 l = local_len(element) 267 result += local_VarintSize(l) + l 268 return result 269 return RepeatedFieldSize 270 else: 271 def FieldSize(value): 272 l = local_len(value) 273 return tag_size + local_VarintSize(l) + l 274 return FieldSize 275 276 277def GroupSizer(field_number, is_repeated, is_packed): 278 """Returns a sizer for a group field.""" 279 280 tag_size = _TagSize(field_number) * 2 281 assert not is_packed 282 if is_repeated: 283 def RepeatedFieldSize(value): 284 result = tag_size * len(value) 285 for element in value: 286 result += element.ByteSize() 287 return result 288 return RepeatedFieldSize 289 else: 290 def FieldSize(value): 291 return tag_size + value.ByteSize() 292 return FieldSize 293 294 295def MessageSizer(field_number, is_repeated, is_packed): 296 """Returns a sizer for a message field.""" 297 298 tag_size = _TagSize(field_number) 299 local_VarintSize = _VarintSize 300 assert not is_packed 301 if is_repeated: 302 def RepeatedFieldSize(value): 303 result = tag_size * len(value) 304 for element in value: 305 l = element.ByteSize() 306 result += local_VarintSize(l) + l 307 return result 308 return RepeatedFieldSize 309 else: 310 def FieldSize(value): 311 l = value.ByteSize() 312 return tag_size + local_VarintSize(l) + l 313 return FieldSize 314 315 316# -------------------------------------------------------------------- 317# MessageSet is special. 318 319 320def MessageSetItemSizer(field_number): 321 """Returns a sizer for extensions of MessageSet. 322 323 The message set message looks like this: 324 message MessageSet { 325 repeated group Item = 1 { 326 required int32 type_id = 2; 327 required string message = 3; 328 } 329 } 330 """ 331 static_size = (_TagSize(1) * 2 + _TagSize(2) + _VarintSize(field_number) + 332 _TagSize(3)) 333 local_VarintSize = _VarintSize 334 335 def FieldSize(value): 336 l = value.ByteSize() 337 return static_size + local_VarintSize(l) + l 338 339 return FieldSize 340 341 342# ==================================================================== 343# Encoders! 344 345 346def _VarintEncoder(): 347 """Return an encoder for a basic varint value (does not include tag).""" 348 349 local_chr = _PY2 and chr or (lambda x: bytes((x,))) ##PY25 350##!PY25 local_chr = chr if bytes is str else lambda x: bytes((x,)) 351 def EncodeVarint(write, value): 352 bits = value & 0x7f 353 value >>= 7 354 while value: 355 write(local_chr(0x80|bits)) 356 bits = value & 0x7f 357 value >>= 7 358 return write(local_chr(bits)) 359 360 return EncodeVarint 361 362 363def _SignedVarintEncoder(): 364 """Return an encoder for a basic signed varint value (does not include 365 tag).""" 366 367 local_chr = _PY2 and chr or (lambda x: bytes((x,))) ##PY25 368##!PY25 local_chr = chr if bytes is str else lambda x: bytes((x,)) 369 def EncodeSignedVarint(write, value): 370 if value < 0: 371 value += (1 << 64) 372 bits = value & 0x7f 373 value >>= 7 374 while value: 375 write(local_chr(0x80|bits)) 376 bits = value & 0x7f 377 value >>= 7 378 return write(local_chr(bits)) 379 380 return EncodeSignedVarint 381 382 383_EncodeVarint = _VarintEncoder() 384_EncodeSignedVarint = _SignedVarintEncoder() 385 386 387def _VarintBytes(value): 388 """Encode the given integer as a varint and return the bytes. This is only 389 called at startup time so it doesn't need to be fast.""" 390 391 pieces = [] 392 _EncodeVarint(pieces.append, value) 393 return "".encode("latin1").join(pieces) ##PY25 394##!PY25 return b"".join(pieces) 395 396 397def TagBytes(field_number, wire_type): 398 """Encode the given tag and return the bytes. Only called at startup.""" 399 400 return _VarintBytes(wire_format.PackTag(field_number, wire_type)) 401 402# -------------------------------------------------------------------- 403# As with sizers (see above), we have a number of common encoder 404# implementations. 405 406 407def _SimpleEncoder(wire_type, encode_value, compute_value_size): 408 """Return a constructor for an encoder for fields of a particular type. 409 410 Args: 411 wire_type: The field's wire type, for encoding tags. 412 encode_value: A function which encodes an individual value, e.g. 413 _EncodeVarint(). 414 compute_value_size: A function which computes the size of an individual 415 value, e.g. _VarintSize(). 416 """ 417 418 def SpecificEncoder(field_number, is_repeated, is_packed): 419 if is_packed: 420 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 421 local_EncodeVarint = _EncodeVarint 422 def EncodePackedField(write, value): 423 write(tag_bytes) 424 size = 0 425 for element in value: 426 size += compute_value_size(element) 427 local_EncodeVarint(write, size) 428 for element in value: 429 encode_value(write, element) 430 return EncodePackedField 431 elif is_repeated: 432 tag_bytes = TagBytes(field_number, wire_type) 433 def EncodeRepeatedField(write, value): 434 for element in value: 435 write(tag_bytes) 436 encode_value(write, element) 437 return EncodeRepeatedField 438 else: 439 tag_bytes = TagBytes(field_number, wire_type) 440 def EncodeField(write, value): 441 write(tag_bytes) 442 return encode_value(write, value) 443 return EncodeField 444 445 return SpecificEncoder 446 447 448def _ModifiedEncoder(wire_type, encode_value, compute_value_size, modify_value): 449 """Like SimpleEncoder but additionally invokes modify_value on every value 450 before passing it to encode_value. Usually modify_value is ZigZagEncode.""" 451 452 def SpecificEncoder(field_number, is_repeated, is_packed): 453 if is_packed: 454 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 455 local_EncodeVarint = _EncodeVarint 456 def EncodePackedField(write, value): 457 write(tag_bytes) 458 size = 0 459 for element in value: 460 size += compute_value_size(modify_value(element)) 461 local_EncodeVarint(write, size) 462 for element in value: 463 encode_value(write, modify_value(element)) 464 return EncodePackedField 465 elif is_repeated: 466 tag_bytes = TagBytes(field_number, wire_type) 467 def EncodeRepeatedField(write, value): 468 for element in value: 469 write(tag_bytes) 470 encode_value(write, modify_value(element)) 471 return EncodeRepeatedField 472 else: 473 tag_bytes = TagBytes(field_number, wire_type) 474 def EncodeField(write, value): 475 write(tag_bytes) 476 return encode_value(write, modify_value(value)) 477 return EncodeField 478 479 return SpecificEncoder 480 481 482def _StructPackEncoder(wire_type, format): 483 """Return a constructor for an encoder for a fixed-width field. 484 485 Args: 486 wire_type: The field's wire type, for encoding tags. 487 format: The format string to pass to struct.pack(). 488 """ 489 490 value_size = struct.calcsize(format) 491 492 def SpecificEncoder(field_number, is_repeated, is_packed): 493 local_struct_pack = struct.pack 494 if is_packed: 495 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 496 local_EncodeVarint = _EncodeVarint 497 def EncodePackedField(write, value): 498 write(tag_bytes) 499 local_EncodeVarint(write, len(value) * value_size) 500 for element in value: 501 write(local_struct_pack(format, element)) 502 return EncodePackedField 503 elif is_repeated: 504 tag_bytes = TagBytes(field_number, wire_type) 505 def EncodeRepeatedField(write, value): 506 for element in value: 507 write(tag_bytes) 508 write(local_struct_pack(format, element)) 509 return EncodeRepeatedField 510 else: 511 tag_bytes = TagBytes(field_number, wire_type) 512 def EncodeField(write, value): 513 write(tag_bytes) 514 return write(local_struct_pack(format, value)) 515 return EncodeField 516 517 return SpecificEncoder 518 519 520def _FloatingPointEncoder(wire_type, format): 521 """Return a constructor for an encoder for float fields. 522 523 This is like StructPackEncoder, but catches errors that may be due to 524 passing non-finite floating-point values to struct.pack, and makes a 525 second attempt to encode those values. 526 527 Args: 528 wire_type: The field's wire type, for encoding tags. 529 format: The format string to pass to struct.pack(). 530 """ 531 532 b = _PY2 and (lambda x:x) or (lambda x:x.encode('latin1')) ##PY25 533 value_size = struct.calcsize(format) 534 if value_size == 4: 535 def EncodeNonFiniteOrRaise(write, value): 536 # Remember that the serialized form uses little-endian byte order. 537 if value == _POS_INF: 538 write(b('\x00\x00\x80\x7F')) ##PY25 539##!PY25 write(b'\x00\x00\x80\x7F') 540 elif value == _NEG_INF: 541 write(b('\x00\x00\x80\xFF')) ##PY25 542##!PY25 write(b'\x00\x00\x80\xFF') 543 elif value != value: # NaN 544 write(b('\x00\x00\xC0\x7F')) ##PY25 545##!PY25 write(b'\x00\x00\xC0\x7F') 546 else: 547 raise 548 elif value_size == 8: 549 def EncodeNonFiniteOrRaise(write, value): 550 if value == _POS_INF: 551 write(b('\x00\x00\x00\x00\x00\x00\xF0\x7F')) ##PY25 552##!PY25 write(b'\x00\x00\x00\x00\x00\x00\xF0\x7F') 553 elif value == _NEG_INF: 554 write(b('\x00\x00\x00\x00\x00\x00\xF0\xFF')) ##PY25 555##!PY25 write(b'\x00\x00\x00\x00\x00\x00\xF0\xFF') 556 elif value != value: # NaN 557 write(b('\x00\x00\x00\x00\x00\x00\xF8\x7F')) ##PY25 558##!PY25 write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F') 559 else: 560 raise 561 else: 562 raise ValueError('Can\'t encode floating-point values that are ' 563 '%d bytes long (only 4 or 8)' % value_size) 564 565 def SpecificEncoder(field_number, is_repeated, is_packed): 566 local_struct_pack = struct.pack 567 if is_packed: 568 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 569 local_EncodeVarint = _EncodeVarint 570 def EncodePackedField(write, value): 571 write(tag_bytes) 572 local_EncodeVarint(write, len(value) * value_size) 573 for element in value: 574 # This try/except block is going to be faster than any code that 575 # we could write to check whether element is finite. 576 try: 577 write(local_struct_pack(format, element)) 578 except SystemError: 579 EncodeNonFiniteOrRaise(write, element) 580 return EncodePackedField 581 elif is_repeated: 582 tag_bytes = TagBytes(field_number, wire_type) 583 def EncodeRepeatedField(write, value): 584 for element in value: 585 write(tag_bytes) 586 try: 587 write(local_struct_pack(format, element)) 588 except SystemError: 589 EncodeNonFiniteOrRaise(write, element) 590 return EncodeRepeatedField 591 else: 592 tag_bytes = TagBytes(field_number, wire_type) 593 def EncodeField(write, value): 594 write(tag_bytes) 595 try: 596 write(local_struct_pack(format, value)) 597 except SystemError: 598 EncodeNonFiniteOrRaise(write, value) 599 return EncodeField 600 601 return SpecificEncoder 602 603 604# ==================================================================== 605# Here we declare an encoder constructor for each field type. These work 606# very similarly to sizer constructors, described earlier. 607 608 609Int32Encoder = Int64Encoder = EnumEncoder = _SimpleEncoder( 610 wire_format.WIRETYPE_VARINT, _EncodeSignedVarint, _SignedVarintSize) 611 612UInt32Encoder = UInt64Encoder = _SimpleEncoder( 613 wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize) 614 615SInt32Encoder = SInt64Encoder = _ModifiedEncoder( 616 wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize, 617 wire_format.ZigZagEncode) 618 619# Note that Python conveniently guarantees that when using the '<' prefix on 620# formats, they will also have the same size across all platforms (as opposed 621# to without the prefix, where their sizes depend on the C compiler's basic 622# type sizes). 623Fixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<I') 624Fixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<Q') 625SFixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<i') 626SFixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<q') 627FloatEncoder = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED32, '<f') 628DoubleEncoder = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED64, '<d') 629 630 631def BoolEncoder(field_number, is_repeated, is_packed): 632 """Returns an encoder for a boolean field.""" 633 634##!PY25 false_byte = b'\x00' 635##!PY25 true_byte = b'\x01' 636 false_byte = '\x00'.encode('latin1') ##PY25 637 true_byte = '\x01'.encode('latin1') ##PY25 638 if is_packed: 639 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 640 local_EncodeVarint = _EncodeVarint 641 def EncodePackedField(write, value): 642 write(tag_bytes) 643 local_EncodeVarint(write, len(value)) 644 for element in value: 645 if element: 646 write(true_byte) 647 else: 648 write(false_byte) 649 return EncodePackedField 650 elif is_repeated: 651 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT) 652 def EncodeRepeatedField(write, value): 653 for element in value: 654 write(tag_bytes) 655 if element: 656 write(true_byte) 657 else: 658 write(false_byte) 659 return EncodeRepeatedField 660 else: 661 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT) 662 def EncodeField(write, value): 663 write(tag_bytes) 664 if value: 665 return write(true_byte) 666 return write(false_byte) 667 return EncodeField 668 669 670def StringEncoder(field_number, is_repeated, is_packed): 671 """Returns an encoder for a string field.""" 672 673 tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 674 local_EncodeVarint = _EncodeVarint 675 local_len = len 676 assert not is_packed 677 if is_repeated: 678 def EncodeRepeatedField(write, value): 679 for element in value: 680 encoded = element.encode('utf-8') 681 write(tag) 682 local_EncodeVarint(write, local_len(encoded)) 683 write(encoded) 684 return EncodeRepeatedField 685 else: 686 def EncodeField(write, value): 687 encoded = value.encode('utf-8') 688 write(tag) 689 local_EncodeVarint(write, local_len(encoded)) 690 return write(encoded) 691 return EncodeField 692 693 694def BytesEncoder(field_number, is_repeated, is_packed): 695 """Returns an encoder for a bytes field.""" 696 697 tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 698 local_EncodeVarint = _EncodeVarint 699 local_len = len 700 assert not is_packed 701 if is_repeated: 702 def EncodeRepeatedField(write, value): 703 for element in value: 704 write(tag) 705 local_EncodeVarint(write, local_len(element)) 706 write(element) 707 return EncodeRepeatedField 708 else: 709 def EncodeField(write, value): 710 write(tag) 711 local_EncodeVarint(write, local_len(value)) 712 return write(value) 713 return EncodeField 714 715 716def GroupEncoder(field_number, is_repeated, is_packed): 717 """Returns an encoder for a group field.""" 718 719 start_tag = TagBytes(field_number, wire_format.WIRETYPE_START_GROUP) 720 end_tag = TagBytes(field_number, wire_format.WIRETYPE_END_GROUP) 721 assert not is_packed 722 if is_repeated: 723 def EncodeRepeatedField(write, value): 724 for element in value: 725 write(start_tag) 726 element._InternalSerialize(write) 727 write(end_tag) 728 return EncodeRepeatedField 729 else: 730 def EncodeField(write, value): 731 write(start_tag) 732 value._InternalSerialize(write) 733 return write(end_tag) 734 return EncodeField 735 736 737def MessageEncoder(field_number, is_repeated, is_packed): 738 """Returns an encoder for a message field.""" 739 740 tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 741 local_EncodeVarint = _EncodeVarint 742 assert not is_packed 743 if is_repeated: 744 def EncodeRepeatedField(write, value): 745 for element in value: 746 write(tag) 747 local_EncodeVarint(write, element.ByteSize()) 748 element._InternalSerialize(write) 749 return EncodeRepeatedField 750 else: 751 def EncodeField(write, value): 752 write(tag) 753 local_EncodeVarint(write, value.ByteSize()) 754 return value._InternalSerialize(write) 755 return EncodeField 756 757 758# -------------------------------------------------------------------- 759# As before, MessageSet is special. 760 761 762def MessageSetItemEncoder(field_number): 763 """Encoder for extensions of MessageSet. 764 765 The message set message looks like this: 766 message MessageSet { 767 repeated group Item = 1 { 768 required int32 type_id = 2; 769 required string message = 3; 770 } 771 } 772 """ 773 start_bytes = "".encode("latin1").join([ ##PY25 774##!PY25 start_bytes = b"".join([ 775 TagBytes(1, wire_format.WIRETYPE_START_GROUP), 776 TagBytes(2, wire_format.WIRETYPE_VARINT), 777 _VarintBytes(field_number), 778 TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED)]) 779 end_bytes = TagBytes(1, wire_format.WIRETYPE_END_GROUP) 780 local_EncodeVarint = _EncodeVarint 781 782 def EncodeField(write, value): 783 write(start_bytes) 784 local_EncodeVarint(write, value.ByteSize()) 785 value._InternalSerialize(write) 786 return write(end_bytes) 787 788 return EncodeField 789