店播爬取Python脚本

encoder.py 28KB

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