Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.11/site-packages/google/protobuf/internal/encoder.py: 17%

Shortcuts on this page

r m x   toggle line displays

j k   next/prev highlighted chunk

0   (zero) top of page

1   (one) first highlighted chunk

497 statements  

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