BinaryEncoder.swift 5.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Sources/SwiftProtobuf/BinaryEncoder.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. /// Encoder for Binary Protocol Buffer format
  17. internal struct BinaryEncoder {
  18. private var pointer: UnsafeMutableRawPointer
  19. private var buffer: UnsafeMutableRawBufferPointer
  20. init(forWritingInto buffer: UnsafeMutableRawBufferPointer) {
  21. self.buffer = buffer
  22. self.pointer = buffer.baseAddress!
  23. }
  24. private mutating func append(_ byte: UInt8) {
  25. pointer.storeBytes(of: byte, as: UInt8.self)
  26. pointer = pointer.advanced(by: 1)
  27. }
  28. private mutating func append<Bytes: SwiftProtobufContiguousBytes>(contentsOf bytes: Bytes) {
  29. bytes.withUnsafeBytes { dataPointer in
  30. if let baseAddress = dataPointer.baseAddress, dataPointer.count > 0 {
  31. pointer.copyMemory(from: baseAddress, byteCount: dataPointer.count)
  32. advance(dataPointer.count)
  33. }
  34. }
  35. }
  36. internal var used: Int {
  37. buffer.baseAddress!.distance(to: pointer)
  38. }
  39. internal var remainder: UnsafeMutableRawBufferPointer {
  40. UnsafeMutableRawBufferPointer(
  41. start: pointer,
  42. count: buffer.count - used
  43. )
  44. }
  45. internal mutating func advance(_ bytes: Int) {
  46. pointer = pointer.advanced(by: bytes)
  47. }
  48. @discardableResult
  49. private mutating func append(contentsOf bufferPointer: UnsafeRawBufferPointer) -> Int {
  50. let count = bufferPointer.count
  51. if let baseAddress = bufferPointer.baseAddress, count > 0 {
  52. pointer.copyMemory(from: baseAddress, byteCount: count)
  53. }
  54. pointer = pointer.advanced(by: count)
  55. return count
  56. }
  57. mutating func appendUnknown(data: Data) {
  58. append(contentsOf: data)
  59. }
  60. mutating func startField(fieldNumber: Int, wireFormat: WireFormat) {
  61. startField(tag: FieldTag(fieldNumber: fieldNumber, wireFormat: wireFormat))
  62. }
  63. mutating func startField(tag: FieldTag) {
  64. putVarInt(value: UInt64(tag.rawValue))
  65. }
  66. mutating func putVarInt(value: UInt64) {
  67. var v = value
  68. while v > 127 {
  69. append(UInt8(v & 0x7f | 0x80))
  70. v >>= 7
  71. }
  72. append(UInt8(v))
  73. }
  74. mutating func putVarInt(value: Int64) {
  75. putVarInt(value: UInt64(bitPattern: value))
  76. }
  77. mutating func putVarInt(value: Int) {
  78. putVarInt(value: Int64(value))
  79. }
  80. mutating func putZigZagVarInt(value: Int64) {
  81. let coded = ZigZag.encoded(value)
  82. putVarInt(value: coded)
  83. }
  84. mutating func putBoolValue(value: Bool) {
  85. append(value ? 1 : 0)
  86. }
  87. mutating func putFixedUInt64(value: UInt64) {
  88. var v = value.littleEndian
  89. let n = MemoryLayout<UInt64>.size
  90. pointer.copyMemory(from: &v, byteCount: n)
  91. pointer = pointer.advanced(by: n)
  92. }
  93. mutating func putFixedUInt32(value: UInt32) {
  94. var v = value.littleEndian
  95. let n = MemoryLayout<UInt32>.size
  96. pointer.copyMemory(from: &v, byteCount: n)
  97. pointer = pointer.advanced(by: n)
  98. }
  99. mutating func putFloatValue(value: Float) {
  100. let n = MemoryLayout<Float>.size
  101. var v = value.bitPattern.littleEndian
  102. pointer.copyMemory(from: &v, byteCount: n)
  103. pointer = pointer.advanced(by: n)
  104. }
  105. mutating func putDoubleValue(value: Double) {
  106. let n = MemoryLayout<Double>.size
  107. var v = value.bitPattern.littleEndian
  108. pointer.copyMemory(from: &v, byteCount: n)
  109. pointer = pointer.advanced(by: n)
  110. }
  111. // Write a string field, including the leading index/tag value.
  112. mutating func putStringValue(value: String) {
  113. let utf8 = value.utf8
  114. // If the String does not support an internal representation in a form
  115. // of contiguous storage, body is not called and nil is returned.
  116. let isAvailable = utf8.withContiguousStorageIfAvailable { (body: UnsafeBufferPointer<UInt8>) -> Int in
  117. putVarInt(value: body.count)
  118. return append(contentsOf: UnsafeRawBufferPointer(body))
  119. }
  120. if isAvailable == nil {
  121. let count = utf8.count
  122. putVarInt(value: count)
  123. for b in utf8 {
  124. pointer.storeBytes(of: b, as: UInt8.self)
  125. pointer = pointer.advanced(by: 1)
  126. }
  127. }
  128. }
  129. mutating func putBytesValue<Bytes: SwiftProtobufContiguousBytes>(value: Bytes) {
  130. putVarInt(value: value.count)
  131. append(contentsOf: value)
  132. }
  133. }