BinaryEncodingSizeVisitor.swift 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505
  1. // Sources/SwiftProtobuf/BinaryEncodingSizeVisitor.swift - Binary size calculation support
  2. //
  3. // Copyright (c) 2014 - 2016 Apple Inc. and the project authors
  4. // Licensed under Apache License v2.0 with Runtime Library Exception
  5. //
  6. // See LICENSE.txt for license information:
  7. // https://github.com/apple/swift-protobuf/blob/main/LICENSE.txt
  8. //
  9. // -----------------------------------------------------------------------------
  10. ///
  11. /// Visitor used during binary encoding that precalcuates the size of a
  12. /// serialized message.
  13. ///
  14. // -----------------------------------------------------------------------------
  15. import Foundation
  16. /// Visitor that calculates the binary-encoded size of a message so that a
  17. /// properly sized `Data` or `UInt8` array can be pre-allocated before
  18. /// serialization.
  19. internal struct BinaryEncodingSizeVisitor: Visitor {
  20. /// Accumulates the required size of the message during traversal.
  21. var serializedSize: Int = 0
  22. init() {}
  23. mutating func visitUnknown(bytes: Data) throws {
  24. serializedSize += bytes.count
  25. }
  26. mutating func visitSingularFloatField(value: Float, fieldNumber: Int) throws {
  27. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
  28. serializedSize += tagSize + MemoryLayout<Float>.size
  29. }
  30. mutating func visitSingularDoubleField(value: Double, fieldNumber: Int) throws {
  31. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
  32. serializedSize += tagSize + MemoryLayout<Double>.size
  33. }
  34. mutating func visitSingularInt32Field(value: Int32, fieldNumber: Int) throws {
  35. try visitSingularInt64Field(value: Int64(value), fieldNumber: fieldNumber)
  36. }
  37. mutating func visitSingularInt64Field(value: Int64, fieldNumber: Int) throws {
  38. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
  39. serializedSize += tagSize + Varint.encodedSize(of: value)
  40. }
  41. mutating func visitSingularUInt32Field(value: UInt32, fieldNumber: Int) throws {
  42. try visitSingularUInt64Field(value: UInt64(value), fieldNumber: fieldNumber)
  43. }
  44. mutating func visitSingularUInt64Field(value: UInt64, fieldNumber: Int) throws {
  45. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
  46. serializedSize += tagSize + Varint.encodedSize(of: value)
  47. }
  48. mutating func visitSingularSInt32Field(value: Int32, fieldNumber: Int) throws {
  49. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
  50. serializedSize += tagSize + Varint.encodedSize(of: ZigZag.encoded(value))
  51. }
  52. mutating func visitSingularSInt64Field(value: Int64, fieldNumber: Int) throws {
  53. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
  54. serializedSize += tagSize + Varint.encodedSize(of: ZigZag.encoded(value))
  55. }
  56. mutating func visitSingularFixed32Field(value: UInt32, fieldNumber: Int) throws {
  57. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
  58. serializedSize += tagSize + MemoryLayout<UInt32>.size
  59. }
  60. mutating func visitSingularFixed64Field(value: UInt64, fieldNumber: Int) throws {
  61. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
  62. serializedSize += tagSize + MemoryLayout<UInt64>.size
  63. }
  64. mutating func visitSingularSFixed32Field(value: Int32, fieldNumber: Int) throws {
  65. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
  66. serializedSize += tagSize + MemoryLayout<Int32>.size
  67. }
  68. mutating func visitSingularSFixed64Field(value: Int64, fieldNumber: Int) throws {
  69. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
  70. serializedSize += tagSize + MemoryLayout<Int64>.size
  71. }
  72. mutating func visitSingularBoolField(value: Bool, fieldNumber: Int) throws {
  73. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
  74. serializedSize += tagSize + 1
  75. }
  76. mutating func visitSingularStringField(value: String, fieldNumber: Int) throws {
  77. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  78. let count = value.utf8.count
  79. serializedSize += tagSize + Varint.encodedSize(of: Int64(count)) + count
  80. }
  81. mutating func visitSingularBytesField(value: Data, fieldNumber: Int) throws {
  82. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  83. let count = value.count
  84. serializedSize += tagSize + Varint.encodedSize(of: Int64(count)) + count
  85. }
  86. // The default impls for visitRepeated*Field would work, but by implementing
  87. // these directly, the calculation for the tag overhead can be optimized and
  88. // the fixed width fields can be simple multiplication.
  89. mutating func visitRepeatedFloatField(value: [Float], fieldNumber: Int) throws {
  90. assert(!value.isEmpty)
  91. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
  92. serializedSize += tagSize * value.count + MemoryLayout<Float>.size * value.count
  93. }
  94. mutating func visitRepeatedDoubleField(value: [Double], fieldNumber: Int) throws {
  95. assert(!value.isEmpty)
  96. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
  97. serializedSize += tagSize * value.count + MemoryLayout<Double>.size * value.count
  98. }
  99. mutating func visitRepeatedInt32Field(value: [Int32], fieldNumber: Int) throws {
  100. assert(!value.isEmpty)
  101. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
  102. let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
  103. serializedSize += tagSize * value.count + dataSize
  104. }
  105. mutating func visitRepeatedInt64Field(value: [Int64], fieldNumber: Int) throws {
  106. assert(!value.isEmpty)
  107. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
  108. let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
  109. serializedSize += tagSize * value.count + dataSize
  110. }
  111. mutating func visitRepeatedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
  112. assert(!value.isEmpty)
  113. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
  114. let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
  115. serializedSize += tagSize * value.count + dataSize
  116. }
  117. mutating func visitRepeatedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
  118. assert(!value.isEmpty)
  119. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
  120. let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
  121. serializedSize += tagSize * value.count + dataSize
  122. }
  123. mutating func visitRepeatedSInt32Field(value: [Int32], fieldNumber: Int) throws {
  124. assert(!value.isEmpty)
  125. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
  126. let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
  127. serializedSize += tagSize * value.count + dataSize
  128. }
  129. mutating func visitRepeatedSInt64Field(value: [Int64], fieldNumber: Int) throws {
  130. assert(!value.isEmpty)
  131. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
  132. let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
  133. serializedSize += tagSize * value.count + dataSize
  134. }
  135. mutating func visitRepeatedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
  136. assert(!value.isEmpty)
  137. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
  138. serializedSize += tagSize * value.count + MemoryLayout<UInt32>.size * value.count
  139. }
  140. mutating func visitRepeatedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
  141. assert(!value.isEmpty)
  142. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
  143. serializedSize += tagSize * value.count + MemoryLayout<UInt64>.size * value.count
  144. }
  145. mutating func visitRepeatedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
  146. assert(!value.isEmpty)
  147. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed32).encodedSize
  148. serializedSize += tagSize * value.count + MemoryLayout<Int32>.size * value.count
  149. }
  150. mutating func visitRepeatedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
  151. assert(!value.isEmpty)
  152. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .fixed64).encodedSize
  153. serializedSize += tagSize * value.count + MemoryLayout<Int64>.size * value.count
  154. }
  155. mutating func visitRepeatedBoolField(value: [Bool], fieldNumber: Int) throws {
  156. assert(!value.isEmpty)
  157. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .varint).encodedSize
  158. serializedSize += tagSize * value.count + 1 * value.count
  159. }
  160. mutating func visitRepeatedStringField(value: [String], fieldNumber: Int) throws {
  161. assert(!value.isEmpty)
  162. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  163. let dataSize = value.reduce(0) {
  164. let count = $1.utf8.count
  165. return $0 + Varint.encodedSize(of: Int64(count)) + count
  166. }
  167. serializedSize += tagSize * value.count + dataSize
  168. }
  169. mutating func visitRepeatedBytesField(value: [Data], fieldNumber: Int) throws {
  170. assert(!value.isEmpty)
  171. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  172. let dataSize = value.reduce(0) {
  173. let count = $1.count
  174. return $0 + Varint.encodedSize(of: Int64(count)) + count
  175. }
  176. serializedSize += tagSize * value.count + dataSize
  177. }
  178. // Packed field handling.
  179. mutating func visitPackedFloatField(value: [Float], fieldNumber: Int) throws {
  180. assert(!value.isEmpty)
  181. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  182. let dataSize = value.count * MemoryLayout<Float>.size
  183. serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
  184. }
  185. mutating func visitPackedDoubleField(value: [Double], fieldNumber: Int) throws {
  186. assert(!value.isEmpty)
  187. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  188. let dataSize = value.count * MemoryLayout<Double>.size
  189. serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
  190. }
  191. mutating func visitPackedInt32Field(value: [Int32], fieldNumber: Int) throws {
  192. assert(!value.isEmpty)
  193. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  194. let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
  195. serializedSize +=
  196. tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
  197. }
  198. mutating func visitPackedInt64Field(value: [Int64], fieldNumber: Int) throws {
  199. assert(!value.isEmpty)
  200. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  201. let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
  202. serializedSize +=
  203. tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
  204. }
  205. mutating func visitPackedSInt32Field(value: [Int32], fieldNumber: Int) throws {
  206. assert(!value.isEmpty)
  207. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  208. let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
  209. serializedSize +=
  210. tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
  211. }
  212. mutating func visitPackedSInt64Field(value: [Int64], fieldNumber: Int) throws {
  213. assert(!value.isEmpty)
  214. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  215. let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
  216. serializedSize +=
  217. tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
  218. }
  219. mutating func visitPackedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
  220. assert(!value.isEmpty)
  221. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  222. let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
  223. serializedSize +=
  224. tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
  225. }
  226. mutating func visitPackedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
  227. assert(!value.isEmpty)
  228. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  229. let dataSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
  230. serializedSize +=
  231. tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
  232. }
  233. mutating func visitPackedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
  234. assert(!value.isEmpty)
  235. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  236. let dataSize = value.count * MemoryLayout<UInt32>.size
  237. serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
  238. }
  239. mutating func visitPackedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
  240. assert(!value.isEmpty)
  241. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  242. let dataSize = value.count * MemoryLayout<UInt64>.size
  243. serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
  244. }
  245. mutating func visitPackedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
  246. assert(!value.isEmpty)
  247. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  248. let dataSize = value.count * MemoryLayout<Int32>.size
  249. serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
  250. }
  251. mutating func visitPackedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
  252. assert(!value.isEmpty)
  253. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  254. let dataSize = value.count * MemoryLayout<Int64>.size
  255. serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
  256. }
  257. mutating func visitPackedBoolField(value: [Bool], fieldNumber: Int) throws {
  258. assert(!value.isEmpty)
  259. let tagSize = FieldTag(fieldNumber: fieldNumber, wireFormat: .lengthDelimited).encodedSize
  260. let dataSize = value.count
  261. serializedSize += tagSize + Varint.encodedSize(of: Int64(dataSize)) + dataSize
  262. }
  263. mutating func visitSingularEnumField<E: Enum>(
  264. value: E,
  265. fieldNumber: Int
  266. ) throws {
  267. let tagSize = FieldTag(
  268. fieldNumber: fieldNumber,
  269. wireFormat: .varint
  270. ).encodedSize
  271. serializedSize += tagSize
  272. let dataSize = Varint.encodedSize(of: Int32(truncatingIfNeeded: value.rawValue))
  273. serializedSize += dataSize
  274. }
  275. mutating func visitRepeatedEnumField<E: Enum>(
  276. value: [E],
  277. fieldNumber: Int
  278. ) throws {
  279. assert(!value.isEmpty)
  280. let tagSize = FieldTag(
  281. fieldNumber: fieldNumber,
  282. wireFormat: .varint
  283. ).encodedSize
  284. serializedSize += value.count * tagSize
  285. let dataSize = value.reduce(0) {
  286. $0 + Varint.encodedSize(of: Int32(truncatingIfNeeded: $1.rawValue))
  287. }
  288. serializedSize += dataSize
  289. }
  290. mutating func visitPackedEnumField<E: Enum>(
  291. value: [E],
  292. fieldNumber: Int
  293. ) throws {
  294. assert(!value.isEmpty)
  295. let tagSize = FieldTag(
  296. fieldNumber: fieldNumber,
  297. wireFormat: .varint
  298. ).encodedSize
  299. serializedSize += tagSize
  300. let dataSize = value.reduce(0) {
  301. $0 + Varint.encodedSize(of: Int32(truncatingIfNeeded: $1.rawValue))
  302. }
  303. serializedSize += Varint.encodedSize(of: Int64(dataSize)) + dataSize
  304. }
  305. mutating func visitSingularMessageField<M: Message>(
  306. value: M,
  307. fieldNumber: Int
  308. ) throws {
  309. let tagSize = FieldTag(
  310. fieldNumber: fieldNumber,
  311. wireFormat: .lengthDelimited
  312. ).encodedSize
  313. let messageSize = try value.serializedDataSize()
  314. serializedSize +=
  315. tagSize + Varint.encodedSize(of: UInt64(messageSize)) + messageSize
  316. }
  317. mutating func visitRepeatedMessageField<M: Message>(
  318. value: [M],
  319. fieldNumber: Int
  320. ) throws {
  321. assert(!value.isEmpty)
  322. let tagSize = FieldTag(
  323. fieldNumber: fieldNumber,
  324. wireFormat: .lengthDelimited
  325. ).encodedSize
  326. serializedSize += value.count * tagSize
  327. let dataSize = try value.reduce(0) {
  328. let messageSize = try $1.serializedDataSize()
  329. return $0 + Varint.encodedSize(of: UInt64(messageSize)) + messageSize
  330. }
  331. serializedSize += dataSize
  332. }
  333. mutating func visitSingularGroupField<G: Message>(value: G, fieldNumber: Int) throws {
  334. // The wire format doesn't matter here because the encoded size of the
  335. // integer won't change based on the low three bits.
  336. let tagSize = FieldTag(
  337. fieldNumber: fieldNumber,
  338. wireFormat: .startGroup
  339. ).encodedSize
  340. serializedSize += 2 * tagSize
  341. try value.traverse(visitor: &self)
  342. }
  343. mutating func visitRepeatedGroupField<G: Message>(
  344. value: [G],
  345. fieldNumber: Int
  346. ) throws {
  347. assert(!value.isEmpty)
  348. let tagSize = FieldTag(
  349. fieldNumber: fieldNumber,
  350. wireFormat: .startGroup
  351. ).encodedSize
  352. serializedSize += 2 * value.count * tagSize
  353. for v in value {
  354. try v.traverse(visitor: &self)
  355. }
  356. }
  357. mutating func visitMapField<KeyType, ValueType: MapValueType>(
  358. fieldType: _ProtobufMap<KeyType, ValueType>.Type,
  359. value: _ProtobufMap<KeyType, ValueType>.BaseType,
  360. fieldNumber: Int
  361. ) throws {
  362. let tagSize = FieldTag(
  363. fieldNumber: fieldNumber,
  364. wireFormat: .lengthDelimited
  365. ).encodedSize
  366. for (k, v) in value {
  367. var sizer = BinaryEncodingSizeVisitor()
  368. try KeyType.visitSingular(value: k, fieldNumber: 1, with: &sizer)
  369. try ValueType.visitSingular(value: v, fieldNumber: 2, with: &sizer)
  370. let entrySize = sizer.serializedSize
  371. serializedSize += Varint.encodedSize(of: Int64(entrySize)) + entrySize
  372. }
  373. serializedSize += value.count * tagSize
  374. }
  375. mutating func visitMapField<KeyType, ValueType>(
  376. fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type,
  377. value: _ProtobufEnumMap<KeyType, ValueType>.BaseType,
  378. fieldNumber: Int
  379. ) throws where ValueType.RawValue == Int {
  380. let tagSize = FieldTag(
  381. fieldNumber: fieldNumber,
  382. wireFormat: .lengthDelimited
  383. ).encodedSize
  384. for (k, v) in value {
  385. var sizer = BinaryEncodingSizeVisitor()
  386. try KeyType.visitSingular(value: k, fieldNumber: 1, with: &sizer)
  387. try sizer.visitSingularEnumField(value: v, fieldNumber: 2)
  388. let entrySize = sizer.serializedSize
  389. serializedSize += Varint.encodedSize(of: Int64(entrySize)) + entrySize
  390. }
  391. serializedSize += value.count * tagSize
  392. }
  393. mutating func visitMapField<KeyType, ValueType>(
  394. fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type,
  395. value: _ProtobufMessageMap<KeyType, ValueType>.BaseType,
  396. fieldNumber: Int
  397. ) throws {
  398. let tagSize = FieldTag(
  399. fieldNumber: fieldNumber,
  400. wireFormat: .lengthDelimited
  401. ).encodedSize
  402. for (k, v) in value {
  403. var sizer = BinaryEncodingSizeVisitor()
  404. try KeyType.visitSingular(value: k, fieldNumber: 1, with: &sizer)
  405. try sizer.visitSingularMessageField(value: v, fieldNumber: 2)
  406. let entrySize = sizer.serializedSize
  407. serializedSize += Varint.encodedSize(of: Int64(entrySize)) + entrySize
  408. }
  409. serializedSize += value.count * tagSize
  410. }
  411. mutating func visitExtensionFieldsAsMessageSet(
  412. fields: ExtensionFieldValueSet,
  413. start: Int,
  414. end: Int
  415. ) throws {
  416. var sizer = BinaryEncodingMessageSetSizeVisitor()
  417. try fields.traverse(visitor: &sizer, start: start, end: end)
  418. serializedSize += sizer.serializedSize
  419. }
  420. }
  421. extension BinaryEncodingSizeVisitor {
  422. // Helper Visitor to compute the sizes when writing out the extensions as MessageSets.
  423. internal struct BinaryEncodingMessageSetSizeVisitor: SelectiveVisitor {
  424. var serializedSize: Int = 0
  425. init() {}
  426. mutating func visitSingularMessageField<M: Message>(value: M, fieldNumber: Int) throws {
  427. var groupSize = WireFormat.MessageSet.itemTagsEncodedSize
  428. groupSize += Varint.encodedSize(of: Int32(fieldNumber))
  429. let messageSize = try value.serializedDataSize()
  430. groupSize += Varint.encodedSize(of: UInt64(messageSize)) + messageSize
  431. serializedSize += groupSize
  432. }
  433. // SelectiveVisitor handles the rest.
  434. }
  435. }