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

475 statements  

« prev     ^ index     » next       coverage.py v7.3.2, created at 2023-12-08 06:40 +0000

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