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"""Code for encoding protocol message primitives.
8
9Contains the logic for encoding every logical protocol field type
10into one of the 5 physical wire types.
11
12This code is designed to push the Python interpreter's performance to the
13limits.
14
15The basic idea is that at startup time, for every field (i.e. every
16FieldDescriptor) we construct two functions: a "sizer" and an "encoder". The
17sizer takes a value of this field's type and computes its byte size. The
18encoder takes a writer function and a value. It encodes the value into byte
19strings and invokes the writer function to write those strings. Typically the
20writer function is the write() method of a BytesIO.
21
22We try to do as much work as possible when constructing the writer and the
23sizer rather than when calling them. In particular:
24* We copy any needed global functions to local variables, so that we do not need
25 to do costly global table lookups at runtime.
26* Similarly, we try to do any attribute lookups at startup time if possible.
27* Every field's tag is encoded to bytes at startup, since it can't change at
28 runtime.
29* Whatever component of the field size we can compute at startup, we do.
30* We *avoid* sharing code if doing so would make the code slower and not sharing
31 does not burden us too much. For example, encoders for repeated fields do
32 not just call the encoders for singular fields in a loop because this would
33 add an extra function call overhead for every loop iteration; instead, we
34 manually inline the single-value encoder into the loop.
35* If a Python function lacks a return statement, Python actually generates
36 instructions to pop the result of the last statement off the stack, push
37 None onto the stack, and then return that. If we really don't care what
38 value is returned, then we can save two instructions by returning the
39 result of the last statement. It looks funny but it helps.
40* We assume that type and bounds checking has happened at a higher level.
41"""
42
43__author__ = 'kenton@google.com (Kenton Varda)'
44
45import struct
46
47from google.protobuf.internal import wire_format
48
49# This will overflow and thus become IEEE-754 "infinity". We would use
50# "float('inf')" but it doesn't work on Windows pre-Python-2.6.
51_POS_INF = 1e10000
52_NEG_INF = -_POS_INF
53
54
55def _VarintSize(value):
56 """Compute the size of a varint value."""
57 if value <= 0x7F:
58 return 1
59 if value <= 0x3FFF:
60 return 2
61 if value <= 0x1FFFFF:
62 return 3
63 if value <= 0xFFFFFFF:
64 return 4
65 if value <= 0x7FFFFFFFF:
66 return 5
67 if value <= 0x3FFFFFFFFFF:
68 return 6
69 if value <= 0x1FFFFFFFFFFFF:
70 return 7
71 if value <= 0xFFFFFFFFFFFFFF:
72 return 8
73 if value <= 0x7FFFFFFFFFFFFFFF:
74 return 9
75 return 10
76
77
78def _SignedVarintSize(value):
79 """Compute the size of a signed varint value."""
80 if value < 0:
81 return 10
82 if value <= 0x7F:
83 return 1
84 if value <= 0x3FFF:
85 return 2
86 if value <= 0x1FFFFF:
87 return 3
88 if value <= 0xFFFFFFF:
89 return 4
90 if value <= 0x7FFFFFFFF:
91 return 5
92 if value <= 0x3FFFFFFFFFF:
93 return 6
94 if value <= 0x1FFFFFFFFFFFF:
95 return 7
96 if value <= 0xFFFFFFFFFFFFFF:
97 return 8
98 if value <= 0x7FFFFFFFFFFFFFFF:
99 return 9
100 return 10
101
102
103def _TagSize(field_number):
104 """Returns the number of bytes required to serialize a tag with this field
105
106 number.
107 """
108 # Just pass in type 0, since the type won't affect the tag+type size.
109 return _VarintSize(wire_format.PackTag(field_number, 0))
110
111
112# --------------------------------------------------------------------
113# In this section we define some generic sizers. Each of these functions
114# takes parameters specific to a particular field type, e.g. int32 or fixed64.
115# It returns another function which in turn takes parameters specific to a
116# particular field, e.g. the field number and whether it is repeated or packed.
117# Look at the next section to see how these are used.
118
119
120def _SimpleSizer(compute_value_size):
121 """A sizer which uses the function compute_value_size to compute the size of
122
123 each value. Typically compute_value_size is _VarintSize.
124 """
125
126 def SpecificSizer(field_number, is_repeated, is_packed):
127 tag_size = _TagSize(field_number)
128 if is_packed:
129 local_VarintSize = _VarintSize
130
131 def PackedFieldSize(value):
132 result = 0
133 for element in value:
134 result += compute_value_size(element)
135 return result + local_VarintSize(result) + tag_size
136
137 return PackedFieldSize
138 elif is_repeated:
139
140 def RepeatedFieldSize(value):
141 result = tag_size * len(value)
142 for element in value:
143 result += compute_value_size(element)
144 return result
145
146 return RepeatedFieldSize
147 else:
148
149 def FieldSize(value):
150 return tag_size + compute_value_size(value)
151
152 return FieldSize
153
154 return SpecificSizer
155
156
157def _ModifiedSizer(compute_value_size, modify_value):
158 """Like SimpleSizer, but modify_value is invoked on each value before it is
159
160 passed to compute_value_size. modify_value is typically ZigZagEncode.
161 """
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
168 def PackedFieldSize(value):
169 result = 0
170 for element in value:
171 result += compute_value_size(modify_value(element))
172 return result + local_VarintSize(result) + tag_size
173
174 return PackedFieldSize
175 elif is_repeated:
176
177 def RepeatedFieldSize(value):
178 result = tag_size * len(value)
179 for element in value:
180 result += compute_value_size(modify_value(element))
181 return result
182
183 return RepeatedFieldSize
184 else:
185
186 def FieldSize(value):
187 return tag_size + compute_value_size(modify_value(value))
188
189 return FieldSize
190
191 return SpecificSizer
192
193
194def _FixedSizer(value_size):
195 """Like _SimpleSizer except for a fixed-size field.
196
197 The input is the size of one value.
198 """
199
200 def SpecificSizer(field_number, is_repeated, is_packed):
201 tag_size = _TagSize(field_number)
202 if is_packed:
203 local_VarintSize = _VarintSize
204
205 def PackedFieldSize(value):
206 result = len(value) * value_size
207 return result + local_VarintSize(result) + tag_size
208
209 return PackedFieldSize
210 elif is_repeated:
211 element_size = value_size + tag_size
212
213 def RepeatedFieldSize(value):
214 return len(value) * element_size
215
216 return RepeatedFieldSize
217 else:
218 field_size = value_size + tag_size
219
220 def FieldSize(value):
221 return field_size
222
223 return FieldSize
224
225 return SpecificSizer
226
227
228# ====================================================================
229# Here we declare a sizer constructor for each field type. Each "sizer
230# constructor" is a function that takes (field_number, is_repeated, is_packed)
231# as parameters and returns a sizer, which in turn takes a field value as
232# a parameter and returns its encoded size.
233
234Int32Sizer = Int64Sizer = EnumSizer = _SimpleSizer(_SignedVarintSize)
235
236UInt32Sizer = UInt64Sizer = _SimpleSizer(_VarintSize)
237
238SInt32Sizer = SInt64Sizer = _ModifiedSizer(
239 _SignedVarintSize, wire_format.ZigZagEncode
240)
241
242Fixed32Sizer = SFixed32Sizer = FloatSizer = _FixedSizer(4)
243Fixed64Sizer = SFixed64Sizer = DoubleSizer = _FixedSizer(8)
244
245BoolSizer = _FixedSizer(1)
246
247
248def StringSizer(field_number, is_repeated, is_packed):
249 """Returns a sizer for a string field."""
250
251 tag_size = _TagSize(field_number)
252 local_VarintSize = _VarintSize
253 local_len = len
254 assert not is_packed
255 if is_repeated:
256
257 def RepeatedFieldSize(value):
258 result = tag_size * len(value)
259 for element in value:
260 l = local_len(element.encode('utf-8'))
261 result += local_VarintSize(l) + l
262 return result
263
264 return RepeatedFieldSize
265 else:
266
267 def FieldSize(value):
268 l = local_len(value.encode('utf-8'))
269 return tag_size + local_VarintSize(l) + l
270
271 return FieldSize
272
273
274def BytesSizer(field_number, is_repeated, is_packed):
275 """Returns a sizer for a bytes field."""
276
277 tag_size = _TagSize(field_number)
278 local_VarintSize = _VarintSize
279 local_len = len
280 assert not is_packed
281 if is_repeated:
282
283 def RepeatedFieldSize(value):
284 result = tag_size * len(value)
285 for element in value:
286 l = local_len(element)
287 result += local_VarintSize(l) + l
288 return result
289
290 return RepeatedFieldSize
291 else:
292
293 def FieldSize(value):
294 l = local_len(value)
295 return tag_size + local_VarintSize(l) + l
296
297 return FieldSize
298
299
300def GroupSizer(field_number, is_repeated, is_packed):
301 """Returns a sizer for a group field."""
302
303 tag_size = _TagSize(field_number) * 2
304 assert not is_packed
305 if is_repeated:
306
307 def RepeatedFieldSize(value):
308 result = tag_size * len(value)
309 for element in value:
310 result += element.ByteSize()
311 return result
312
313 return RepeatedFieldSize
314 else:
315
316 def FieldSize(value):
317 return tag_size + value.ByteSize()
318
319 return FieldSize
320
321
322def MessageSizer(field_number, is_repeated, is_packed):
323 """Returns a sizer for a message field."""
324
325 tag_size = _TagSize(field_number)
326 local_VarintSize = _VarintSize
327 assert not is_packed
328 if is_repeated:
329
330 def RepeatedFieldSize(value):
331 result = tag_size * len(value)
332 for element in value:
333 l = element.ByteSize()
334 result += local_VarintSize(l) + l
335 return result
336
337 return RepeatedFieldSize
338 else:
339
340 def FieldSize(value):
341 l = value.ByteSize()
342 return tag_size + local_VarintSize(l) + l
343
344 return FieldSize
345
346
347# --------------------------------------------------------------------
348# MessageSet is special: it needs custom logic to compute its size properly.
349
350
351def MessageSetItemSizer(field_number):
352 """Returns a sizer for extensions of MessageSet.
353
354 The message set message looks like this:
355 message MessageSet {
356 repeated group Item = 1 {
357 required int32 type_id = 2;
358 required string message = 3;
359 }
360 }
361 """
362 static_size = (
363 _TagSize(1) * 2 + _TagSize(2) + _VarintSize(field_number) + _TagSize(3)
364 )
365 local_VarintSize = _VarintSize
366
367 def FieldSize(value):
368 l = value.ByteSize()
369 return static_size + local_VarintSize(l) + l
370
371 return FieldSize
372
373
374# --------------------------------------------------------------------
375# Map is special: it needs custom logic to compute its size properly.
376
377
378def MapSizer(field_descriptor, key_sizer, value_sizer):
379 """Returns a sizer for a map field."""
380
381 def FieldSize(map_value):
382 tag_size = _TagSize(field_descriptor.number)
383 local_VarintSize = _VarintSize
384
385 total = 0
386 for key in map_value:
387 val = map_value[key]
388 entry_size = key_sizer(key) + value_sizer(val)
389 total += tag_size + local_VarintSize(entry_size) + entry_size
390
391 return total
392
393 return FieldSize
394
395
396# ====================================================================
397# Encoders!
398
399
400def _VarintEncoder():
401 """Return an encoder for a basic varint value (does not include tag)."""
402
403 local_int2byte = struct.Struct('>B').pack
404
405 def EncodeVarint(write, value, unused_deterministic=None):
406 bits = value & 0x7F
407 value >>= 7
408 while value:
409 write(local_int2byte(0x80 | bits))
410 bits = value & 0x7F
411 value >>= 7
412 return write(local_int2byte(bits))
413
414 return EncodeVarint
415
416
417def _SignedVarintEncoder():
418 """Return an encoder for a basic signed varint value (does not include
419
420 tag).
421 """
422
423 local_int2byte = struct.Struct('>B').pack
424
425 def EncodeSignedVarint(write, value, unused_deterministic=None):
426 if value < 0:
427 value += 1 << 64
428 bits = value & 0x7F
429 value >>= 7
430 while value:
431 write(local_int2byte(0x80 | bits))
432 bits = value & 0x7F
433 value >>= 7
434 return write(local_int2byte(bits))
435
436 return EncodeSignedVarint
437
438
439_EncodeVarint = _VarintEncoder()
440_EncodeSignedVarint = _SignedVarintEncoder()
441
442
443def _VarintBytes(value):
444 """Encode the given integer as a varint and return the bytes.
445
446 This is only called at startup time so it doesn't need to be fast.
447 """
448
449 pieces = []
450 _EncodeVarint(pieces.append, value, True)
451 return b''.join(pieces)
452
453
454def TagBytes(field_number, wire_type):
455 """Encode the given tag and return the bytes. Only called at startup."""
456
457 return bytes(_VarintBytes(wire_format.PackTag(field_number, wire_type)))
458
459
460# --------------------------------------------------------------------
461# As with sizers (see above), we have a number of common encoder
462# implementations.
463
464
465def _SimpleEncoder(wire_type, encode_value, compute_value_size):
466 """Return a constructor for an encoder for fields of a particular type.
467
468 Args:
469 wire_type: The field's wire type, for encoding tags.
470 encode_value: A function which encodes an individual value, e.g.
471 _EncodeVarint().
472 compute_value_size: A function which computes the size of an individual
473 value, e.g. _VarintSize().
474 """
475
476 def SpecificEncoder(field_number, is_repeated, is_packed):
477 if is_packed:
478 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
479 local_EncodeVarint = _EncodeVarint
480
481 def EncodePackedField(write, value, deterministic):
482 write(tag_bytes)
483 size = 0
484 for element in value:
485 size += compute_value_size(element)
486 local_EncodeVarint(write, size, deterministic)
487 for element in value:
488 encode_value(write, element, deterministic)
489
490 return EncodePackedField
491 elif is_repeated:
492 tag_bytes = TagBytes(field_number, wire_type)
493
494 def EncodeRepeatedField(write, value, deterministic):
495 for element in value:
496 write(tag_bytes)
497 encode_value(write, element, deterministic)
498
499 return EncodeRepeatedField
500 else:
501 tag_bytes = TagBytes(field_number, wire_type)
502
503 def EncodeField(write, value, deterministic):
504 write(tag_bytes)
505 return encode_value(write, value, deterministic)
506
507 return EncodeField
508
509 return SpecificEncoder
510
511
512def _ModifiedEncoder(wire_type, encode_value, compute_value_size, modify_value):
513 """Like SimpleEncoder but additionally invokes modify_value on every value
514
515 before passing it to encode_value. Usually modify_value is ZigZagEncode.
516 """
517
518 def SpecificEncoder(field_number, is_repeated, is_packed):
519 if is_packed:
520 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
521 local_EncodeVarint = _EncodeVarint
522
523 def EncodePackedField(write, value, deterministic):
524 write(tag_bytes)
525 size = 0
526 for element in value:
527 size += compute_value_size(modify_value(element))
528 local_EncodeVarint(write, size, deterministic)
529 for element in value:
530 encode_value(write, modify_value(element), deterministic)
531
532 return EncodePackedField
533 elif is_repeated:
534 tag_bytes = TagBytes(field_number, wire_type)
535
536 def EncodeRepeatedField(write, value, deterministic):
537 for element in value:
538 write(tag_bytes)
539 encode_value(write, modify_value(element), deterministic)
540
541 return EncodeRepeatedField
542 else:
543 tag_bytes = TagBytes(field_number, wire_type)
544
545 def EncodeField(write, value, deterministic):
546 write(tag_bytes)
547 return encode_value(write, modify_value(value), deterministic)
548
549 return EncodeField
550
551 return SpecificEncoder
552
553
554def _StructPackEncoder(wire_type, format):
555 """Return a constructor for an encoder for a fixed-width field.
556
557 Args:
558 wire_type: The field's wire type, for encoding tags.
559 format: The format string to pass to struct.pack().
560 """
561
562 value_size = struct.calcsize(format)
563
564 def SpecificEncoder(field_number, is_repeated, is_packed):
565 local_struct_pack = struct.pack
566 if is_packed:
567 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
568 local_EncodeVarint = _EncodeVarint
569
570 def EncodePackedField(write, value, deterministic):
571 write(tag_bytes)
572 local_EncodeVarint(write, len(value) * value_size, deterministic)
573 for element in value:
574 write(local_struct_pack(format, element))
575
576 return EncodePackedField
577 elif is_repeated:
578 tag_bytes = TagBytes(field_number, wire_type)
579
580 def EncodeRepeatedField(write, value, unused_deterministic=None):
581 for element in value:
582 write(tag_bytes)
583 write(local_struct_pack(format, element))
584
585 return EncodeRepeatedField
586 else:
587 tag_bytes = TagBytes(field_number, wire_type)
588
589 def EncodeField(write, value, unused_deterministic=None):
590 write(tag_bytes)
591 return write(local_struct_pack(format, value))
592
593 return EncodeField
594
595 return SpecificEncoder
596
597
598def _FloatingPointEncoder(wire_type, format):
599 """Return a constructor for an encoder for float fields.
600
601 This is like StructPackEncoder, but catches errors that may be due to
602 passing non-finite floating-point values to struct.pack, and makes a
603 second attempt to encode those values.
604
605 Args:
606 wire_type: The field's wire type, for encoding tags.
607 format: The format string to pass to struct.pack().
608 """
609
610 value_size = struct.calcsize(format)
611 if value_size == 4:
612
613 def EncodeNonFiniteOrRaise(write, value):
614 # Remember that the serialized form uses little-endian byte order.
615 if value == _POS_INF:
616 write(b'\x00\x00\x80\x7F')
617 elif value == _NEG_INF:
618 write(b'\x00\x00\x80\xFF')
619 elif value != value: # NaN
620 write(b'\x00\x00\xC0\x7F')
621 else:
622 raise
623
624 elif value_size == 8:
625
626 def EncodeNonFiniteOrRaise(write, value):
627 if value == _POS_INF:
628 write(b'\x00\x00\x00\x00\x00\x00\xF0\x7F')
629 elif value == _NEG_INF:
630 write(b'\x00\x00\x00\x00\x00\x00\xF0\xFF')
631 elif value != value: # NaN
632 write(b'\x00\x00\x00\x00\x00\x00\xF8\x7F')
633 else:
634 raise
635
636 else:
637 raise ValueError(
638 "Can't encode floating-point values that are "
639 '%d bytes long (only 4 or 8)' % value_size
640 )
641
642 def SpecificEncoder(field_number, is_repeated, is_packed):
643 local_struct_pack = struct.pack
644 if is_packed:
645 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
646 local_EncodeVarint = _EncodeVarint
647
648 def EncodePackedField(write, value, deterministic):
649 write(tag_bytes)
650 local_EncodeVarint(write, len(value) * value_size, deterministic)
651 for element in value:
652 # This try/except block is going to be faster than any code that
653 # we could write to check whether element is finite.
654 try:
655 write(local_struct_pack(format, element))
656 except SystemError:
657 EncodeNonFiniteOrRaise(write, element)
658
659 return EncodePackedField
660 elif is_repeated:
661 tag_bytes = TagBytes(field_number, wire_type)
662
663 def EncodeRepeatedField(write, value, unused_deterministic=None):
664 for element in value:
665 write(tag_bytes)
666 try:
667 write(local_struct_pack(format, element))
668 except SystemError:
669 EncodeNonFiniteOrRaise(write, element)
670
671 return EncodeRepeatedField
672 else:
673 tag_bytes = TagBytes(field_number, wire_type)
674
675 def EncodeField(write, value, unused_deterministic=None):
676 write(tag_bytes)
677 try:
678 write(local_struct_pack(format, value))
679 except SystemError:
680 EncodeNonFiniteOrRaise(write, value)
681
682 return EncodeField
683
684 return SpecificEncoder
685
686
687# ====================================================================
688# Here we declare an encoder constructor for each field type. These work
689# very similarly to sizer constructors, described earlier.
690
691Int32Encoder = Int64Encoder = EnumEncoder = _SimpleEncoder(
692 wire_format.WIRETYPE_VARINT, _EncodeSignedVarint, _SignedVarintSize
693)
694
695UInt32Encoder = UInt64Encoder = _SimpleEncoder(
696 wire_format.WIRETYPE_VARINT, _EncodeVarint, _VarintSize
697)
698
699SInt32Encoder = SInt64Encoder = _ModifiedEncoder(
700 wire_format.WIRETYPE_VARINT,
701 _EncodeVarint,
702 _VarintSize,
703 wire_format.ZigZagEncode,
704)
705
706# Note that Python conveniently guarantees that when using the '<' prefix on
707# formats, they will also have the same size across all platforms (as opposed
708# to without the prefix, where their sizes depend on the C compiler's basic
709# type sizes).
710Fixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<I')
711Fixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<Q')
712SFixed32Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED32, '<i')
713SFixed64Encoder = _StructPackEncoder(wire_format.WIRETYPE_FIXED64, '<q')
714FloatEncoder = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED32, '<f')
715DoubleEncoder = _FloatingPointEncoder(wire_format.WIRETYPE_FIXED64, '<d')
716
717
718def BoolEncoder(field_number, is_repeated, is_packed):
719 """Returns an encoder for a boolean field."""
720
721 false_byte = b'\x00'
722 true_byte = b'\x01'
723 if is_packed:
724 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
725 local_EncodeVarint = _EncodeVarint
726
727 def EncodePackedField(write, value, deterministic):
728 write(tag_bytes)
729 local_EncodeVarint(write, len(value), deterministic)
730 for element in value:
731 if element:
732 write(true_byte)
733 else:
734 write(false_byte)
735
736 return EncodePackedField
737 elif is_repeated:
738 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
739
740 def EncodeRepeatedField(write, value, unused_deterministic=None):
741 for element in value:
742 write(tag_bytes)
743 if element:
744 write(true_byte)
745 else:
746 write(false_byte)
747
748 return EncodeRepeatedField
749 else:
750 tag_bytes = TagBytes(field_number, wire_format.WIRETYPE_VARINT)
751
752 def EncodeField(write, value, unused_deterministic=None):
753 write(tag_bytes)
754 if value:
755 return write(true_byte)
756 return write(false_byte)
757
758 return EncodeField
759
760
761def StringEncoder(field_number, is_repeated, is_packed):
762 """Returns an encoder for a string field."""
763
764 tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
765 local_EncodeVarint = _EncodeVarint
766 local_len = len
767 assert not is_packed
768 if is_repeated:
769
770 def EncodeRepeatedField(write, value, deterministic):
771 for element in value:
772 encoded = element.encode('utf-8')
773 write(tag)
774 local_EncodeVarint(write, local_len(encoded), deterministic)
775 write(encoded)
776
777 return EncodeRepeatedField
778 else:
779
780 def EncodeField(write, value, deterministic):
781 encoded = value.encode('utf-8')
782 write(tag)
783 local_EncodeVarint(write, local_len(encoded), deterministic)
784 return write(encoded)
785
786 return EncodeField
787
788
789def BytesEncoder(field_number, is_repeated, is_packed):
790 """Returns an encoder for a bytes field."""
791
792 tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
793 local_EncodeVarint = _EncodeVarint
794 local_len = len
795 assert not is_packed
796 if is_repeated:
797
798 def EncodeRepeatedField(write, value, deterministic):
799 for element in value:
800 write(tag)
801 local_EncodeVarint(write, local_len(element), deterministic)
802 write(element)
803
804 return EncodeRepeatedField
805 else:
806
807 def EncodeField(write, value, deterministic):
808 write(tag)
809 local_EncodeVarint(write, local_len(value), deterministic)
810 return write(value)
811
812 return EncodeField
813
814
815def GroupEncoder(field_number, is_repeated, is_packed):
816 """Returns an encoder for a group field."""
817
818 start_tag = TagBytes(field_number, wire_format.WIRETYPE_START_GROUP)
819 end_tag = TagBytes(field_number, wire_format.WIRETYPE_END_GROUP)
820 assert not is_packed
821 if is_repeated:
822
823 def EncodeRepeatedField(write, value, deterministic):
824 for element in value:
825 write(start_tag)
826 element._InternalSerialize(write, deterministic)
827 write(end_tag)
828
829 return EncodeRepeatedField
830 else:
831
832 def EncodeField(write, value, deterministic):
833 write(start_tag)
834 value._InternalSerialize(write, deterministic)
835 return write(end_tag)
836
837 return EncodeField
838
839
840def MessageEncoder(field_number, is_repeated, is_packed):
841 """Returns an encoder for a message field."""
842
843 tag = TagBytes(field_number, wire_format.WIRETYPE_LENGTH_DELIMITED)
844 local_EncodeVarint = _EncodeVarint
845 assert not is_packed
846 if is_repeated:
847
848 def EncodeRepeatedField(write, value, deterministic):
849 for element in value:
850 write(tag)
851 local_EncodeVarint(write, element.ByteSize(), deterministic)
852 element._InternalSerialize(write, deterministic)
853
854 return EncodeRepeatedField
855 else:
856
857 def EncodeField(write, value, deterministic):
858 write(tag)
859 local_EncodeVarint(write, value.ByteSize(), deterministic)
860 return value._InternalSerialize(write, deterministic)
861
862 return EncodeField
863
864
865# --------------------------------------------------------------------
866# As before, MessageSet is special.
867
868
869def MessageSetItemEncoder(field_number):
870 """Encoder for extensions of MessageSet.
871
872 The message set message looks like this:
873 message MessageSet {
874 repeated group Item = 1 {
875 required int32 type_id = 2;
876 required string message = 3;
877 }
878 }
879 """
880 start_bytes = b''.join([
881 TagBytes(1, wire_format.WIRETYPE_START_GROUP),
882 TagBytes(2, wire_format.WIRETYPE_VARINT),
883 _VarintBytes(field_number),
884 TagBytes(3, wire_format.WIRETYPE_LENGTH_DELIMITED),
885 ])
886 end_bytes = TagBytes(1, wire_format.WIRETYPE_END_GROUP)
887 local_EncodeVarint = _EncodeVarint
888
889 def EncodeField(write, value, deterministic):
890 write(start_bytes)
891 local_EncodeVarint(write, value.ByteSize(), deterministic)
892 value._InternalSerialize(write, deterministic)
893 return write(end_bytes)
894
895 return EncodeField
896
897
898# --------------------------------------------------------------------
899# As before, Map is special.
900
901
902def MapEncoder(
903 field_descriptor, key_encoder, value_encoder, key_sizer, value_sizer
904):
905 """Encoder for map fields.
906
907 Maps always have a wire format like this:
908 message MapEntry {
909 key_type key = 1;
910 value_type value = 2;
911 }
912 repeated MapEntry map = N;
913 """
914
915 tag_bytes = TagBytes(
916 field_descriptor.number, wire_format.WIRETYPE_LENGTH_DELIMITED
917 )
918 local_EncodeVarint = _EncodeVarint
919
920 def EncodeField(write, value, deterministic):
921 value_keys = sorted(value.keys()) if deterministic else value
922 for key in value_keys:
923 val = value[key]
924 entry_size = key_sizer(key) + value_sizer(val)
925
926 write(tag_bytes)
927 local_EncodeVarint(write, entry_size, deterministic)
928 key_encoder(write, key, deterministic)
929 value_encoder(write, val, deterministic)
930
931 return EncodeField