BinaryEncodingVisitor.swift 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402
  1. // Sources/SwiftProtobuf/BinaryEncodingVisitor.swift - Binary encoding 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. /// Core support for protobuf binary encoding. Note that this is built
  12. /// on the general traversal machinery.
  13. ///
  14. // -----------------------------------------------------------------------------
  15. import Foundation
  16. /// Visitor that encodes a message graph in the protobuf binary wire format.
  17. internal struct BinaryEncodingVisitor: Visitor {
  18. private let options: BinaryEncodingOptions
  19. var encoder: BinaryEncoder
  20. /// Creates a new visitor that writes the binary-coded message into the memory
  21. /// at the given pointer.
  22. ///
  23. /// - Precondition: `pointer` must point to an allocated block of memory that
  24. /// is large enough to hold the entire encoded message. For performance
  25. /// reasons, the encoder does not make any attempts to verify this.
  26. init(forWritingInto buffer: UnsafeMutableRawBufferPointer, options: BinaryEncodingOptions) {
  27. self.encoder = BinaryEncoder(forWritingInto: buffer)
  28. self.options = options
  29. }
  30. mutating func visitUnknown(bytes: Data) throws {
  31. encoder.appendUnknown(data: bytes)
  32. }
  33. mutating func visitSingularFloatField(value: Float, fieldNumber: Int) throws {
  34. encoder.startField(fieldNumber: fieldNumber, wireFormat: .fixed32)
  35. encoder.putFloatValue(value: value)
  36. }
  37. mutating func visitSingularDoubleField(value: Double, fieldNumber: Int) throws {
  38. encoder.startField(fieldNumber: fieldNumber, wireFormat: .fixed64)
  39. encoder.putDoubleValue(value: value)
  40. }
  41. mutating func visitSingularInt64Field(value: Int64, fieldNumber: Int) throws {
  42. try visitSingularUInt64Field(value: UInt64(bitPattern: value), fieldNumber: fieldNumber)
  43. }
  44. mutating func visitSingularUInt64Field(value: UInt64, fieldNumber: Int) throws {
  45. encoder.startField(fieldNumber: fieldNumber, wireFormat: .varint)
  46. encoder.putVarInt(value: value)
  47. }
  48. mutating func visitSingularSInt32Field(value: Int32, fieldNumber: Int) throws {
  49. try visitSingularSInt64Field(value: Int64(value), fieldNumber: fieldNumber)
  50. }
  51. mutating func visitSingularSInt64Field(value: Int64, fieldNumber: Int) throws {
  52. try visitSingularUInt64Field(value: ZigZag.encoded(value), fieldNumber: fieldNumber)
  53. }
  54. mutating func visitSingularFixed32Field(value: UInt32, fieldNumber: Int) throws {
  55. encoder.startField(fieldNumber: fieldNumber, wireFormat: .fixed32)
  56. encoder.putFixedUInt32(value: value)
  57. }
  58. mutating func visitSingularFixed64Field(value: UInt64, fieldNumber: Int) throws {
  59. encoder.startField(fieldNumber: fieldNumber, wireFormat: .fixed64)
  60. encoder.putFixedUInt64(value: value)
  61. }
  62. mutating func visitSingularSFixed32Field(value: Int32, fieldNumber: Int) throws {
  63. try visitSingularFixed32Field(value: UInt32(bitPattern: value), fieldNumber: fieldNumber)
  64. }
  65. mutating func visitSingularSFixed64Field(value: Int64, fieldNumber: Int) throws {
  66. try visitSingularFixed64Field(value: UInt64(bitPattern: value), fieldNumber: fieldNumber)
  67. }
  68. mutating func visitSingularBoolField(value: Bool, fieldNumber: Int) throws {
  69. try visitSingularUInt64Field(value: value ? 1 : 0, fieldNumber: fieldNumber)
  70. }
  71. mutating func visitSingularStringField(value: String, fieldNumber: Int) throws {
  72. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  73. encoder.putStringValue(value: value)
  74. }
  75. mutating func visitSingularBytesField(value: Data, fieldNumber: Int) throws {
  76. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  77. encoder.putBytesValue(value: value)
  78. }
  79. mutating func visitSingularEnumField<E: Enum>(
  80. value: E,
  81. fieldNumber: Int
  82. ) throws {
  83. try visitSingularUInt64Field(
  84. value: UInt64(bitPattern: Int64(value.rawValue)),
  85. fieldNumber: fieldNumber
  86. )
  87. }
  88. mutating func visitSingularMessageField<M: Message>(
  89. value: M,
  90. fieldNumber: Int
  91. ) throws {
  92. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  93. let length = try value.serializedDataSize()
  94. encoder.putVarInt(value: length)
  95. try value.traverse(visitor: &self)
  96. }
  97. mutating func visitSingularGroupField<G: Message>(value: G, fieldNumber: Int) throws {
  98. encoder.startField(fieldNumber: fieldNumber, wireFormat: .startGroup)
  99. try value.traverse(visitor: &self)
  100. encoder.startField(fieldNumber: fieldNumber, wireFormat: .endGroup)
  101. }
  102. // Repeated fields are handled by the default implementations in Visitor.swift
  103. // Packed Fields
  104. mutating func visitPackedFloatField(value: [Float], fieldNumber: Int) throws {
  105. assert(!value.isEmpty)
  106. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  107. encoder.putVarInt(value: value.count * MemoryLayout<Float>.size)
  108. for v in value {
  109. encoder.putFloatValue(value: v)
  110. }
  111. }
  112. mutating func visitPackedDoubleField(value: [Double], fieldNumber: Int) throws {
  113. assert(!value.isEmpty)
  114. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  115. encoder.putVarInt(value: value.count * MemoryLayout<Double>.size)
  116. for v in value {
  117. encoder.putDoubleValue(value: v)
  118. }
  119. }
  120. mutating func visitPackedInt32Field(value: [Int32], fieldNumber: Int) throws {
  121. assert(!value.isEmpty)
  122. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  123. let packedSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
  124. encoder.putVarInt(value: packedSize)
  125. for v in value {
  126. encoder.putVarInt(value: Int64(v))
  127. }
  128. }
  129. mutating func visitPackedInt64Field(value: [Int64], fieldNumber: Int) throws {
  130. assert(!value.isEmpty)
  131. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  132. let packedSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
  133. encoder.putVarInt(value: packedSize)
  134. for v in value {
  135. encoder.putVarInt(value: v)
  136. }
  137. }
  138. mutating func visitPackedSInt32Field(value: [Int32], fieldNumber: Int) throws {
  139. assert(!value.isEmpty)
  140. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  141. let packedSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
  142. encoder.putVarInt(value: packedSize)
  143. for v in value {
  144. encoder.putZigZagVarInt(value: Int64(v))
  145. }
  146. }
  147. mutating func visitPackedSInt64Field(value: [Int64], fieldNumber: Int) throws {
  148. assert(!value.isEmpty)
  149. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  150. let packedSize = value.reduce(0) { $0 + Varint.encodedSize(of: ZigZag.encoded($1)) }
  151. encoder.putVarInt(value: packedSize)
  152. for v in value {
  153. encoder.putZigZagVarInt(value: v)
  154. }
  155. }
  156. mutating func visitPackedUInt32Field(value: [UInt32], fieldNumber: Int) throws {
  157. assert(!value.isEmpty)
  158. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  159. let packedSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
  160. encoder.putVarInt(value: packedSize)
  161. for v in value {
  162. encoder.putVarInt(value: UInt64(v))
  163. }
  164. }
  165. mutating func visitPackedUInt64Field(value: [UInt64], fieldNumber: Int) throws {
  166. assert(!value.isEmpty)
  167. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  168. let packedSize = value.reduce(0) { $0 + Varint.encodedSize(of: $1) }
  169. encoder.putVarInt(value: packedSize)
  170. for v in value {
  171. encoder.putVarInt(value: v)
  172. }
  173. }
  174. mutating func visitPackedFixed32Field(value: [UInt32], fieldNumber: Int) throws {
  175. assert(!value.isEmpty)
  176. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  177. encoder.putVarInt(value: value.count * MemoryLayout<UInt32>.size)
  178. for v in value {
  179. encoder.putFixedUInt32(value: v)
  180. }
  181. }
  182. mutating func visitPackedFixed64Field(value: [UInt64], fieldNumber: Int) throws {
  183. assert(!value.isEmpty)
  184. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  185. encoder.putVarInt(value: value.count * MemoryLayout<UInt64>.size)
  186. for v in value {
  187. encoder.putFixedUInt64(value: v)
  188. }
  189. }
  190. mutating func visitPackedSFixed32Field(value: [Int32], fieldNumber: Int) throws {
  191. assert(!value.isEmpty)
  192. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  193. encoder.putVarInt(value: value.count * MemoryLayout<Int32>.size)
  194. for v in value {
  195. encoder.putFixedUInt32(value: UInt32(bitPattern: v))
  196. }
  197. }
  198. mutating func visitPackedSFixed64Field(value: [Int64], fieldNumber: Int) throws {
  199. assert(!value.isEmpty)
  200. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  201. encoder.putVarInt(value: value.count * MemoryLayout<Int64>.size)
  202. for v in value {
  203. encoder.putFixedUInt64(value: UInt64(bitPattern: v))
  204. }
  205. }
  206. mutating func visitPackedBoolField(value: [Bool], fieldNumber: Int) throws {
  207. assert(!value.isEmpty)
  208. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  209. encoder.putVarInt(value: value.count)
  210. for v in value {
  211. encoder.putVarInt(value: v ? 1 : 0)
  212. }
  213. }
  214. mutating func visitPackedEnumField<E: Enum>(value: [E], fieldNumber: Int) throws {
  215. assert(!value.isEmpty)
  216. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  217. let packedSize = value.reduce(0) {
  218. $0 + Varint.encodedSize(of: Int32(truncatingIfNeeded: $1.rawValue))
  219. }
  220. encoder.putVarInt(value: packedSize)
  221. for v in value {
  222. encoder.putVarInt(value: v.rawValue)
  223. }
  224. }
  225. mutating func visitMapField<KeyType, ValueType: MapValueType>(
  226. fieldType: _ProtobufMap<KeyType, ValueType>.Type,
  227. value: _ProtobufMap<KeyType, ValueType>.BaseType,
  228. fieldNumber: Int
  229. ) throws {
  230. try iterateAndEncode(
  231. map: value,
  232. fieldNumber: fieldNumber,
  233. isOrderedBefore: KeyType._lessThan,
  234. encodeWithSizer: { sizer, key, value in
  235. try KeyType.visitSingular(value: key, fieldNumber: 1, with: &sizer)
  236. try ValueType.visitSingular(value: value, fieldNumber: 2, with: &sizer)
  237. },
  238. encodeWithVisitor: { visitor, key, value in
  239. try KeyType.visitSingular(value: key, fieldNumber: 1, with: &visitor)
  240. try ValueType.visitSingular(value: value, fieldNumber: 2, with: &visitor)
  241. }
  242. )
  243. }
  244. mutating func visitMapField<KeyType, ValueType>(
  245. fieldType: _ProtobufEnumMap<KeyType, ValueType>.Type,
  246. value: _ProtobufEnumMap<KeyType, ValueType>.BaseType,
  247. fieldNumber: Int
  248. ) throws where ValueType.RawValue == Int {
  249. try iterateAndEncode(
  250. map: value,
  251. fieldNumber: fieldNumber,
  252. isOrderedBefore: KeyType._lessThan,
  253. encodeWithSizer: { sizer, key, value in
  254. try KeyType.visitSingular(value: key, fieldNumber: 1, with: &sizer)
  255. try sizer.visitSingularEnumField(value: value, fieldNumber: 2)
  256. },
  257. encodeWithVisitor: { visitor, key, value in
  258. try KeyType.visitSingular(value: key, fieldNumber: 1, with: &visitor)
  259. try visitor.visitSingularEnumField(value: value, fieldNumber: 2)
  260. }
  261. )
  262. }
  263. mutating func visitMapField<KeyType, ValueType>(
  264. fieldType: _ProtobufMessageMap<KeyType, ValueType>.Type,
  265. value: _ProtobufMessageMap<KeyType, ValueType>.BaseType,
  266. fieldNumber: Int
  267. ) throws {
  268. try iterateAndEncode(
  269. map: value,
  270. fieldNumber: fieldNumber,
  271. isOrderedBefore: KeyType._lessThan,
  272. encodeWithSizer: { sizer, key, value in
  273. try KeyType.visitSingular(value: key, fieldNumber: 1, with: &sizer)
  274. try sizer.visitSingularMessageField(value: value, fieldNumber: 2)
  275. },
  276. encodeWithVisitor: { visitor, key, value in
  277. try KeyType.visitSingular(value: key, fieldNumber: 1, with: &visitor)
  278. try visitor.visitSingularMessageField(value: value, fieldNumber: 2)
  279. }
  280. )
  281. }
  282. /// Helper to encapsulate the common structure of iterating over a map
  283. /// and encoding the keys and values.
  284. private mutating func iterateAndEncode<K, V>(
  285. map: [K: V],
  286. fieldNumber: Int,
  287. isOrderedBefore: (K, K) -> Bool,
  288. encodeWithSizer: (inout BinaryEncodingSizeVisitor, K, V) throws -> Void,
  289. encodeWithVisitor: (inout BinaryEncodingVisitor, K, V) throws -> Void
  290. ) throws {
  291. if options.useDeterministicOrdering {
  292. for (k, v) in map.sorted(by: { isOrderedBefore($0.0, $1.0) }) {
  293. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  294. var sizer = BinaryEncodingSizeVisitor()
  295. try encodeWithSizer(&sizer, k, v)
  296. let entrySize = sizer.serializedSize
  297. encoder.putVarInt(value: entrySize)
  298. try encodeWithVisitor(&self, k, v)
  299. }
  300. } else {
  301. for (k, v) in map {
  302. encoder.startField(fieldNumber: fieldNumber, wireFormat: .lengthDelimited)
  303. var sizer = BinaryEncodingSizeVisitor()
  304. try encodeWithSizer(&sizer, k, v)
  305. let entrySize = sizer.serializedSize
  306. encoder.putVarInt(value: entrySize)
  307. try encodeWithVisitor(&self, k, v)
  308. }
  309. }
  310. }
  311. mutating func visitExtensionFieldsAsMessageSet(
  312. fields: ExtensionFieldValueSet,
  313. start: Int,
  314. end: Int
  315. ) throws {
  316. var subVisitor = BinaryEncodingMessageSetVisitor(encoder: encoder, options: options)
  317. try fields.traverse(visitor: &subVisitor, start: start, end: end)
  318. encoder = subVisitor.encoder
  319. }
  320. }
  321. extension BinaryEncodingVisitor {
  322. // Helper Visitor to when writing out the extensions as MessageSets.
  323. internal struct BinaryEncodingMessageSetVisitor: SelectiveVisitor {
  324. private let options: BinaryEncodingOptions
  325. var encoder: BinaryEncoder
  326. init(encoder: BinaryEncoder, options: BinaryEncodingOptions) {
  327. self.options = options
  328. self.encoder = encoder
  329. }
  330. mutating func visitSingularMessageField<M: Message>(value: M, fieldNumber: Int) throws {
  331. encoder.putVarInt(value: Int64(WireFormat.MessageSet.Tags.itemStart.rawValue))
  332. encoder.putVarInt(value: Int64(WireFormat.MessageSet.Tags.typeId.rawValue))
  333. encoder.putVarInt(value: fieldNumber)
  334. encoder.putVarInt(value: Int64(WireFormat.MessageSet.Tags.message.rawValue))
  335. // Use a normal BinaryEncodingVisitor so any message fields end up in the
  336. // normal wire format (instead of MessageSet format).
  337. let length = try value.serializedDataSize()
  338. encoder.putVarInt(value: length)
  339. // Create the sub encoder after writing the length.
  340. var subVisitor = BinaryEncodingVisitor(
  341. forWritingInto: encoder.remainder,
  342. options: options
  343. )
  344. try value.traverse(visitor: &subVisitor)
  345. encoder.advance(subVisitor.encoder.used)
  346. encoder.putVarInt(value: Int64(WireFormat.MessageSet.Tags.itemEnd.rawValue))
  347. }
  348. // SelectiveVisitor handles the rest.
  349. }
  350. }