1# Protocol Buffers - Google's data interchange format 2# Copyright 2008 Google Inc. All rights reserved. 3# 4# Use of this source code is governed by a BSD-style 5# license that can be found in the LICENSE file or at 6# https://developers.google.com/open-source/licenses/bsd 7 8"""Code for encoding protocol message primitives. 9 10Contains the logic for encoding every logical protocol field type 11into one of the 5 physical wire types. 12 13This code is designed to push the Python interpreter's performance to the 14limits. 15 16The basic idea is that at startup time, for every field (i.e. every 17FieldDescriptor) we construct two functions: a "sizer" and an "encoder". The 18sizer takes a value of this field's type and computes its byte size. The 19encoder takes a writer function and a value. It encodes the value into byte 20strings and invokes the writer function to write those strings. Typically the 21writer function is the write() method of a BytesIO. 22 23We try to do as much work as possible when constructing the writer and the 24sizer rather than when calling them. In particular: 25* We copy any needed global functions to local variables, so that we do not need 26 to do costly global table lookups at runtime. 27* Similarly, we try to do any attribute lookups at startup time if possible. 28* Every field's tag is encoded to bytes at startup, since it can't change at 29 runtime. 30* Whatever component of the field size we can compute at startup, we do. 31* We *avoid* sharing code if doing so would make the code slower and not sharing 32 does not burden us too much. For example, encoders for repeated fields do 33 not just call the encoders for singular fields in a loop because this would 34 add an extra function call overhead for every loop iteration; instead, we 35 manually inline the single-value encoder into the loop. 36* If a Python function lacks a return statement, Python actually generates 37 instructions to pop the result of the last statement off the stack, push 38 None onto the stack, and then return that. If we really don't care what 39 value is returned, then we can save two instructions by returning the 40 result of the last statement. It looks funny but it helps. 41* We assume that type and bounds checking has happened at a higher level. 42""" 43 44__author__ = 'kenton@google.com (Kenton Varda)' 45 46import struct 47 48from google.protobuf.internal import wire_format 49 50 51# This will overflow and thus become IEEE-754 "infinity". We would use 52# "float('inf')" but it doesn't work on Windows pre-Python-2.6. 53_POS_INF = 1e10000 54_NEG_INF = -_POS_INF 55 56 57def _VarintSize(value): 58 """Compute the size of a varint value.""" 59 if value <= 0x7f: return 1 60 if value <= 0x3fff: return 2 61 if value <= 0x1fffff: return 3 62 if value <= 0xfffffff: return 4 63 if value <= 0x7ffffffff: return 5 64 if value <= 0x3ffffffffff: return 6 65 if value <= 0x1ffffffffffff: return 7 66 if value <= 0xffffffffffffff: return 8 67 if value <= 0x7fffffffffffffff: return 9 68 return 10 69 70 71def _SignedVarintSize(value): 72 """Compute the size of a signed varint value.""" 73 if value < 0: return 10 74 if value <= 0x7f: return 1 75 if value <= 0x3fff: return 2 76 if value <= 0x1fffff: return 3 77 if value <= 0xfffffff: return 4 78 if value <= 0x7ffffffff: return 5 79 if value <= 0x3ffffffffff: return 6 80 if value <= 0x1ffffffffffff: return 7 81 if value <= 0xffffffffffffff: return 8 82 if value <= 0x7fffffffffffffff: return 9 83 return 10 84 85 86def _TagSize(field_number): 87 """Returns the number of bytes required to serialize a tag with this field 88 number.""" 89 # Just pass in type 0, since the type won't affect the tag+type size. 90 return _VarintSize(wire_format.PackTag(field_number, 0)) 91 92 93# -------------------------------------------------------------------- 94# In this section we define some generic sizers. Each of these functions 95# takes parameters specific to a particular field type, e.g. int32 or fixed64. 96# It returns another function which in turn takes parameters specific to a 97# particular field, e.g. the field number and whether it is repeated or packed. 98# Look at the next section to see how these are used. 99 100 101def _SimpleSizer(compute_value_size): 102 """A sizer which uses the function compute_value_size to compute the size of 103 each value. Typically compute_value_size is _VarintSize.""" 104 105 def SpecificSizer(field_number, is_repeated, is_packed): 106 tag_size = _TagSize(field_number) 107 if is_packed: 108 local_VarintSize = _VarintSize 109 def PackedFieldSize(value): 110 result = 0 111 for element in value: 112 result += compute_value_size(element) 113 return result + local_VarintSize(result) + tag_size 114 return PackedFieldSize 115 elif is_repeated: 116 def RepeatedFieldSize(value): 117 result = tag_size * len(value) 118 for element in value: 119 result += compute_value_size(element) 120 return result 121 return RepeatedFieldSize 122 else: 123 def FieldSize(value): 124 return tag_size + compute_value_size(value) 125 return FieldSize 126 127 return SpecificSizer 128 129 130def _ModifiedSizer(compute_value_size, modify_value): 131 """Like SimpleSizer, but modify_value is invoked on each value before it is 132 passed to compute_value_size. modify_value is typically ZigZagEncode.""" 133 134 def SpecificSizer(field_number, is_repeated, is_packed): 135 tag_size = _TagSize(field_number) 136 if is_packed: 137 local_VarintSize = _VarintSize 138 def PackedFieldSize(value): 139 result = 0 140 for element in value: 141 result += compute_value_size(modify_value(element)) 142 return result + local_VarintSize(result) + tag_size 143 return PackedFieldSize 144 elif is_repeated: 145 def RepeatedFieldSize(value): 146 result = tag_size * len(value) 147 for element in value: 148 result += compute_value_size(modify_value(element)) 149 return result 150 return RepeatedFieldSize 151 else: 152 def FieldSize(value): 153 return tag_size + compute_value_size(modify_value(value)) 154 return FieldSize 155 156 return SpecificSizer 157 158 159def _FixedSizer(value_size): 160 """Like _SimpleSizer except for a fixed-size field. The input is the size 161 of one value.""" 162 163 def SpecificSizer(field_number, is_repeated, is_packed): 164 tag_size = _TagSize(field_number) 165 if is_packed: 166 local_VarintSize = _VarintSize 167 def PackedFieldSize(value): 168 result = len(value) * value_size 169 return result + local_VarintSize(result) + tag_size 170 return PackedFieldSize 171 elif is_repeated: 172 element_size = value_size + tag_size 173 def RepeatedFieldSize(value): 174 return len(value) * element_size 175 return RepeatedFieldSize 176 else: 177 field_size = value_size + tag_size 178 def FieldSize(value): 179 return field_size 180 return FieldSize 181 182 return SpecificSizer 183 184 185# ==================================================================== 186# Here we declare a sizer constructor for each field type. Each "sizer 187# constructor" is a function that takes (field_number, is_repeated, is_packed) 188# as parameters and returns a sizer, which in turn takes a field value as 189# a parameter and returns its encoded size. 190 191 192Int32Sizer = Int64Sizer = EnumSizer = _SimpleSizer(_SignedVarintSize) 193 194UInt32Sizer = UInt64Sizer = _SimpleSizer(_VarintSize) 195 196SInt32Sizer = SInt64Sizer = _ModifiedSizer( 197 _SignedVarintSize, wire_format.ZigZagEncode) 198 199Fixed32Sizer = SFixed32Sizer = FloatSizer = _FixedSizer(4) 200Fixed64Sizer = SFixed64Sizer = DoubleSizer = _FixedSizer(8) 201 202BoolSizer = _FixedSizer(1) 203 204 205def StringSizer(field_number, is_repeated, is_packed): 206 """Returns a sizer for a string field.""" 207 208 tag_size = _TagSize(field_number) 209 local_VarintSize = _VarintSize 210 local_len = len 211 assert not is_packed 212 if is_repeated: 213 def RepeatedFieldSize(value): 214 result = tag_size * len(value) 215 for element in value: 216 l = local_len(element.encode('utf-8')) 217 result += local_VarintSize(l) + l 218 return result 219 return RepeatedFieldSize 220 else: 221 def FieldSize(value): 222 l = local_len(value.encode('utf-8')) 223 return tag_size + local_VarintSize(l) + l 224 return FieldSize 225 226 227def BytesSizer(field_number, is_repeated, is_packed): 228 """Returns a sizer for a bytes field.""" 229 230 tag_size = _TagSize(field_number) 231 local_VarintSize = _VarintSize 232 local_len = len 233 assert not is_packed 234 if is_repeated: 235 def RepeatedFieldSize(value): 236 result = tag_size * len(value) 237 for element in value: 238 l = local_len(element) 239 result += local_VarintSize(l) + l 240 return result 241 return RepeatedFieldSize 242 else: 243 def FieldSize(value): 244 l = local_len(value) 245 return tag_size + local_VarintSize(l) + l 246 return FieldSize 247 248 249def GroupSizer(field_number, is_repeated, is_packed): 250 """Returns a sizer for a group field.""" 251 252 tag_size = _TagSize(field_number) * 2 253 assert not is_packed 254 if is_repeated: 255 def RepeatedFieldSize(value): 256 result = tag_size * len(value) 257 for element in value: 258 result += element.ByteSize() 259 return result 260 return RepeatedFieldSize 261 else: 262 def FieldSize(value): 263 return tag_size + value.ByteSize() 264 return FieldSize 265 266 267def MessageSizer(field_number, is_repeated, is_packed): 268 """Returns a sizer for a message field.""" 269 270 tag_size = _TagSize(field_number) 271 local_VarintSize = _VarintSize 272 assert not is_packed 273 if is_repeated: 274 def RepeatedFieldSize(value): 275 result = tag_size * len(value) 276 for element in value: 277 l = element.ByteSize() 278 result += local_VarintSize(l) + l 279 return result 280 return RepeatedFieldSize 281 else: 282 def FieldSize(value): 283 l = value.ByteSize() 284 return tag_size + local_VarintSize(l) + l 285 return FieldSize 286 287 288# -------------------------------------------------------------------- 289# MessageSet is special: it needs custom logic to compute its size properly. 290 291 292def MessageSetItemSizer(field_number): 293 """Returns a sizer for extensions of MessageSet. 294 295 The message set message looks like this: 296 message MessageSet { 297 repeated group Item = 1 { 298 required int32 type_id = 2; 299 required string message = 3; 300 } 301 } 302 """ 303 static_size = (_TagSize(1) * 2 + _TagSize(2) + _VarintSize(field_number) + 304 _TagSize(3)) 305 local_VarintSize = _VarintSize 306 307 def FieldSize(value): 308 l = value.ByteSize() 309 return static_size + local_VarintSize(l) + l 310 311 return FieldSize 312 313 314# -------------------------------------------------------------------- 315# Map is special: it needs custom logic to compute its size properly. 316 317 318def MapSizer(field_descriptor, is_message_map): 319 """Returns a sizer for a map field.""" 320 321 # Can't look at field_descriptor.message_type._concrete_class because it may 322 # not have been initialized yet. 323 message_type = field_descriptor.message_type 324 message_sizer = MessageSizer(field_descriptor.number, False, False) 325 326 def FieldSize(map_value): 327 total = 0 328 for key in map_value: 329 value = map_value[key] 330 # It's wasteful to create the messages and throw them away one second 331 # later since we'll do the same for the actual encode. But there's not an 332 # obvious way to avoid this within the current design without tons of code 333 # duplication. For message map, value.ByteSize() should be called to 334 # update the status. 335 entry_msg = message_type._concrete_class(key=key, value=value) 336 total += message_sizer(entry_msg) 337 if is_message_map: 338 value.ByteSize() 339 return total 340 341 return FieldSize 342 343# ==================================================================== 344# Encoders! 345 346 347def _VarintEncoder(): 348 """Return an encoder for a basic varint value (does not include tag).""" 349 350 local_int2byte = struct.Struct('>B').pack 351 352 def EncodeVarint(write, value, unused_deterministic=None): 353 bits = value & 0x7f 354 value >>= 7 355 while value: 356 write(local_int2byte(0x80|bits)) 357 bits = value & 0x7f 358 value >>= 7 359 return write(local_int2byte(bits)) 360 361 return EncodeVarint 362 363 364def _SignedVarintEncoder(): 365 """Return an encoder for a basic signed varint value (does not include 366 tag).""" 367 368 local_int2byte = struct.Struct('>B').pack 369 370 def EncodeSignedVarint(write, value, unused_deterministic=None): 371 if value < 0: 372 value += (1 << 64) 373 bits = value & 0x7f 374 value >>= 7 375 while value: 376 write(local_int2byte(0x80|bits)) 377 bits = value & 0x7f 378 value >>= 7 379 return write(local_int2byte(bits)) 380 381 return EncodeSignedVarint 382 383 384_EncodeVarint = _VarintEncoder() 385_EncodeSignedVarint = _SignedVarintEncoder() 386 387 388def _VarintBytes(value): 389 """Encode the given integer as a varint and return the bytes. This is only 390 called at startup time so it doesn't need to be fast.""" 391 392 pieces = [] 393 _EncodeVarint(pieces.append, value, True) 394 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 bytes(_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, deterministic): 423 write(tag_bytes) 424 size = 0 425 for element in value: 426 size += compute_value_size(element) 427 local_EncodeVarint(write, size, deterministic) 428 for element in value: 429 encode_value(write, element, deterministic) 430 return EncodePackedField 431 elif is_repeated: 432 tag_bytes = TagBytes(field_number, wire_type) 433 def EncodeRepeatedField(write, value, deterministic): 434 for element in value: 435 write(tag_bytes) 436 encode_value(write, element, deterministic) 437 return EncodeRepeatedField 438 else: 439 tag_bytes = TagBytes(field_number, wire_type) 440 def EncodeField(write, value, deterministic): 441 write(tag_bytes) 442 return encode_value(write, value, deterministic) 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, deterministic): 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, deterministic) 462 for element in value: 463 encode_value(write, modify_value(element), deterministic) 464 return EncodePackedField 465 elif is_repeated: 466 tag_bytes = TagBytes(field_number, wire_type) 467 def EncodeRepeatedField(write, value, deterministic): 468 for element in value: 469 write(tag_bytes) 470 encode_value(write, modify_value(element), deterministic) 471 return EncodeRepeatedField 472 else: 473 tag_bytes = TagBytes(field_number, wire_type) 474 def EncodeField(write, value, deterministic): 475 write(tag_bytes) 476 return encode_value(write, modify_value(value), deterministic) 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, deterministic): 498 write(tag_bytes) 499 local_EncodeVarint(write, len(value) * value_size, deterministic) 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, unused_deterministic=None): 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, unused_deterministic=None): 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 value_size = struct.calcsize(format) 533 if value_size == 4: 534 def EncodeNonFiniteOrRaise(write, value): 535 # Remember that the serialized form uses little-endian byte order. 536 if value == _POS_INF: 537 write(b'\x00\x00\x80\x7F') 538 elif value == _NEG_INF: 539 write(b'\x00\x00\x80\xFF') 540 elif value != value: # NaN 541 write(b'\x00\x00\xC0\x7F') 542 else: 543 raise 544 elif value_size == 8: 545 def EncodeNonFiniteOrRaise(write, value): 546 if value == _POS_INF: 547 write(b'\x00\x00\x00\x00\x00\x00\xF0\x7F') 548 elif value == _NEG_INF: 549 write(b'\x00\x00\x00\x00\x00\x00\xF0\xFF') 550 elif value != value: # NaN 551 write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F') 552 else: 553 raise 554 else: 555 raise ValueError('Can\'t encode floating-point values that are ' 556 '%d bytes long (only 4 or 8)' % value_size) 557 558 def SpecificEncoder(field_number, is_repeated, is_packed): 559 local_struct_pack = struct.pack 560 if is_packed: 561 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 562 local_EncodeVarint = _EncodeVarint 563 def EncodePackedField(write, value, deterministic): 564 write(tag_bytes) 565 local_EncodeVarint(write, len(value) * value_size, deterministic) 566 for element in value: 567 # This try/except block is going to be faster than any code that 568 # we could write to check whether element is finite. 569 try: 570 write(local_struct_pack(format, element)) 571 except SystemError: 572 EncodeNonFiniteOrRaise(write, element) 573 return EncodePackedField 574 elif is_repeated: 575 tag_bytes = TagBytes(field_number, wire_type) 576 def EncodeRepeatedField(write, value, unused_deterministic=None): 577 for element in value: 578 write(tag_bytes) 579 try: 580 write(local_struct_pack(format, element)) 581 except SystemError: 582 EncodeNonFiniteOrRaise(write, element) 583 return EncodeRepeatedField 584 else: 585 tag_bytes = TagBytes(field_number, wire_type) 586 def EncodeField(write, value, unused_deterministic=None): 587 write(tag_bytes) 588 try: 589 write(local_struct_pack(format, value)) 590 except SystemError: 591 EncodeNonFiniteOrRaise(write, value) 592 return EncodeField 593 594 return SpecificEncoder 595 596 597# ==================================================================== 598# Here we declare an encoder constructor for each field type. These work 599# very similarly to sizer constructors, described earlier. 600 601 602Int32Encoder = Int64Encoder = EnumEncoder = _SimpleEncoder( 603 wire_format.WIRETYPE_VARINT, _EncodeSignedVarint, _SignedVarintSize) 604 605UInt32Encoder = UInt64Encoder = _SimpleEncoder( 606 wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize) 607 608SInt32Encoder = SInt64Encoder = _ModifiedEncoder( 609 wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize, 610 wire_format.ZigZagEncode) 611 612# Note that Python conveniently guarantees that when using the '<' prefix on 613# formats, they will also have the same size across all platforms (as opposed 614# to without the prefix, where their sizes depend on the C compiler's basic 615# type sizes). 616Fixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<I') 617Fixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<Q') 618SFixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<i') 619SFixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<q') 620FloatEncoder = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED32, '<f') 621DoubleEncoder = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED64, '<d') 622 623 624def BoolEncoder(field_number, is_repeated, is_packed): 625 """Returns an encoder for a boolean field.""" 626 627 false_byte = b'\x00' 628 true_byte = b'\x01' 629 if is_packed: 630 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 631 local_EncodeVarint = _EncodeVarint 632 def EncodePackedField(write, value, deterministic): 633 write(tag_bytes) 634 local_EncodeVarint(write, len(value), deterministic) 635 for element in value: 636 if element: 637 write(true_byte) 638 else: 639 write(false_byte) 640 return EncodePackedField 641 elif is_repeated: 642 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT) 643 def EncodeRepeatedField(write, value, unused_deterministic=None): 644 for element in value: 645 write(tag_bytes) 646 if element: 647 write(true_byte) 648 else: 649 write(false_byte) 650 return EncodeRepeatedField 651 else: 652 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT) 653 def EncodeField(write, value, unused_deterministic=None): 654 write(tag_bytes) 655 if value: 656 return write(true_byte) 657 return write(false_byte) 658 return EncodeField 659 660 661def StringEncoder(field_number, is_repeated, is_packed): 662 """Returns an encoder for a string field.""" 663 664 tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 665 local_EncodeVarint = _EncodeVarint 666 local_len = len 667 assert not is_packed 668 if is_repeated: 669 def EncodeRepeatedField(write, value, deterministic): 670 for element in value: 671 encoded = element.encode('utf-8') 672 write(tag) 673 local_EncodeVarint(write, local_len(encoded), deterministic) 674 write(encoded) 675 return EncodeRepeatedField 676 else: 677 def EncodeField(write, value, deterministic): 678 encoded = value.encode('utf-8') 679 write(tag) 680 local_EncodeVarint(write, local_len(encoded), deterministic) 681 return write(encoded) 682 return EncodeField 683 684 685def BytesEncoder(field_number, is_repeated, is_packed): 686 """Returns an encoder for a bytes field.""" 687 688 tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 689 local_EncodeVarint = _EncodeVarint 690 local_len = len 691 assert not is_packed 692 if is_repeated: 693 def EncodeRepeatedField(write, value, deterministic): 694 for element in value: 695 write(tag) 696 local_EncodeVarint(write, local_len(element), deterministic) 697 write(element) 698 return EncodeRepeatedField 699 else: 700 def EncodeField(write, value, deterministic): 701 write(tag) 702 local_EncodeVarint(write, local_len(value), deterministic) 703 return write(value) 704 return EncodeField 705 706 707def GroupEncoder(field_number, is_repeated, is_packed): 708 """Returns an encoder for a group field.""" 709 710 start_tag = TagBytes(field_number, wire_format.WIRETYPE_START_GROUP) 711 end_tag = TagBytes(field_number, wire_format.WIRETYPE_END_GROUP) 712 assert not is_packed 713 if is_repeated: 714 def EncodeRepeatedField(write, value, deterministic): 715 for element in value: 716 write(start_tag) 717 element._InternalSerialize(write, deterministic) 718 write(end_tag) 719 return EncodeRepeatedField 720 else: 721 def EncodeField(write, value, deterministic): 722 write(start_tag) 723 value._InternalSerialize(write, deterministic) 724 return write(end_tag) 725 return EncodeField 726 727 728def MessageEncoder(field_number, is_repeated, is_packed): 729 """Returns an encoder for a message field.""" 730 731 tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED) 732 local_EncodeVarint = _EncodeVarint 733 assert not is_packed 734 if is_repeated: 735 def EncodeRepeatedField(write, value, deterministic): 736 for element in value: 737 write(tag) 738 local_EncodeVarint(write, element.ByteSize(), deterministic) 739 element._InternalSerialize(write, deterministic) 740 return EncodeRepeatedField 741 else: 742 def EncodeField(write, value, deterministic): 743 write(tag) 744 local_EncodeVarint(write, value.ByteSize(), deterministic) 745 return value._InternalSerialize(write, deterministic) 746 return EncodeField 747 748 749# -------------------------------------------------------------------- 750# As before, MessageSet is special. 751 752 753def MessageSetItemEncoder(field_number): 754 """Encoder for extensions of MessageSet. 755 756 The message set message looks like this: 757 message MessageSet { 758 repeated group Item = 1 { 759 required int32 type_id = 2; 760 required string message = 3; 761 } 762 } 763 """ 764 start_bytes = b"".join([ 765 TagBytes(1, wire_format.WIRETYPE_START_GROUP), 766 TagBytes(2, wire_format.WIRETYPE_VARINT), 767 _VarintBytes(field_number), 768 TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED)]) 769 end_bytes = TagBytes(1, wire_format.WIRETYPE_END_GROUP) 770 local_EncodeVarint = _EncodeVarint 771 772 def EncodeField(write, value, deterministic): 773 write(start_bytes) 774 local_EncodeVarint(write, value.ByteSize(), deterministic) 775 value._InternalSerialize(write, deterministic) 776 return write(end_bytes) 777 778 return EncodeField 779 780 781# -------------------------------------------------------------------- 782# As before, Map is special. 783 784 785def MapEncoder(field_descriptor): 786 """Encoder for extensions of MessageSet. 787 788 Maps always have a wire format like this: 789 message MapEntry { 790 key_type key = 1; 791 value_type value = 2; 792 } 793 repeated MapEntry map = N; 794 """ 795 # Can't look at field_descriptor.message_type._concrete_class because it may 796 # not have been initialized yet. 797 message_type = field_descriptor.message_type 798 encode_message = MessageEncoder(field_descriptor.number, False, False) 799 800 def EncodeField(write, value, deterministic): 801 value_keys = sorted(value.keys()) if deterministic else value 802 for key in value_keys: 803 entry_msg = message_type._concrete_class(key=key, value=value[key]) 804 encode_message(write, entry_msg, deterministic) 805 806 return EncodeField 807