Skip to content

Commit cef408d

Browse files
tbkkathomasvl
authored andcommitted
Use BufferPointer in the BinaryEncoding API
Binary encoders are currently instantiated with a pointer to the beginning of the buffer into which they should encode the data. In every case, we actually have a Swift "buffer pointer" which includes the size of the buffer. As a general cleanup, pass the full buffer pointer into the encoder initializer and adjust the rest of the API a bit to fit better with this approach. This also makes clients agnostic to whether the encoder is working front-to-back or back-to-front.
1 parent 08328aa commit cef408d

File tree

5 files changed

+37
-34
lines changed

5 files changed

+37
-34
lines changed

Sources/SwiftProtobuf/BinaryDecoder.swift

Lines changed: 7 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -874,13 +874,11 @@ internal struct BinaryDecoder: Decoder {
874874
let fieldSize = Varint.encodedSize(of: fieldTag.rawValue) + Varint.encodedSize(of: Int64(bodySize)) + bodySize
875875
var field = Data(count: fieldSize)
876876
field.withUnsafeMutableBytes { (body: UnsafeMutableRawBufferPointer) in
877-
if let baseAddress = body.baseAddress, body.count > 0 {
878-
var encoder = BinaryEncoder(forWritingInto: baseAddress)
879-
encoder.startField(tag: fieldTag)
880-
encoder.putVarInt(value: Int64(bodySize))
881-
for v in extras {
882-
encoder.putVarInt(value: Int64(v))
883-
}
877+
var encoder = BinaryEncoder(forWritingInto: body)
878+
encoder.startField(tag: fieldTag)
879+
encoder.putVarInt(value: Int64(bodySize))
880+
for v in extras {
881+
encoder.putVarInt(value: Int64(v))
884882
}
885883
}
886884
unknownOverride = field
@@ -1247,10 +1245,8 @@ internal struct BinaryDecoder: Decoder {
12471245
let payloadSize = Varint.encodedSize(of: Int64(data.count)) + data.count
12481246
var payload = Data(count: payloadSize)
12491247
payload.withUnsafeMutableBytes { (body: UnsafeMutableRawBufferPointer) in
1250-
if let baseAddress = body.baseAddress, body.count > 0 {
1251-
var encoder = BinaryEncoder(forWritingInto: baseAddress)
1252-
encoder.putBytesValue(value: data)
1253-
}
1248+
var encoder = BinaryEncoder(forWritingInto: body)
1249+
encoder.putBytesValue(value: data)
12541250
}
12551251
fieldData = payload
12561252
} else {

Sources/SwiftProtobuf/BinaryDelimited.swift

Lines changed: 2 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -74,10 +74,8 @@ public enum BinaryDelimited {
7474
let totalSize = Varint.encodedSize(of: UInt64(serialized.count)) + serialized.count
7575
var bytes: [UInt8] = Array(repeating: 0, count: totalSize)
7676
bytes.withUnsafeMutableBytes { (body: UnsafeMutableRawBufferPointer) in
77-
if let baseAddress = body.baseAddress, body.count > 0 {
78-
var encoder = BinaryEncoder(forWritingInto: baseAddress)
79-
encoder.putBytesValue(value: serialized)
80-
}
77+
var encoder = BinaryEncoder(forWritingInto: body)
78+
encoder.putBytesValue(value: serialized)
8179
}
8280

8381
var written: Int = 0

Sources/SwiftProtobuf/BinaryEncoder.swift

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -17,10 +17,12 @@ import Foundation
1717

1818
/// Encoder for Binary Protocol Buffer format
1919
internal struct BinaryEncoder {
20-
internal var pointer: UnsafeMutableRawPointer
20+
private var pointer: UnsafeMutableRawPointer
21+
private var buffer: UnsafeMutableRawBufferPointer
2122

22-
init(forWritingInto pointer: UnsafeMutableRawPointer) {
23-
self.pointer = pointer
23+
init(forWritingInto buffer: UnsafeMutableRawBufferPointer) {
24+
self.buffer = buffer
25+
self.pointer = buffer.baseAddress!
2426
}
2527

2628
private mutating func append(_ byte: UInt8) {
@@ -32,11 +34,24 @@ internal struct BinaryEncoder {
3234
bytes.withUnsafeBytes { dataPointer in
3335
if let baseAddress = dataPointer.baseAddress, dataPointer.count > 0 {
3436
pointer.copyMemory(from: baseAddress, byteCount: dataPointer.count)
35-
pointer = pointer.advanced(by: dataPointer.count)
37+
advance(dataPointer.count)
3638
}
3739
}
3840
}
3941

42+
internal var used: Int {
43+
return buffer.baseAddress!.distance(to: pointer)
44+
}
45+
46+
internal var remainder: UnsafeMutableRawBufferPointer {
47+
return UnsafeMutableRawBufferPointer(start: pointer,
48+
count: buffer.count - used)
49+
}
50+
51+
internal mutating func advance(_ bytes: Int) {
52+
pointer = pointer.advanced(by: bytes)
53+
}
54+
4055
@discardableResult
4156
private mutating func append(contentsOf bufferPointer: UnsafeRawBufferPointer) -> Int {
4257
let count = bufferPointer.count
@@ -47,10 +62,6 @@ internal struct BinaryEncoder {
4762
return count
4863
}
4964

50-
func distance(pointer: UnsafeMutableRawPointer) -> Int {
51-
return pointer.distance(to: self.pointer)
52-
}
53-
5465
mutating func appendUnknown(data: Data) {
5566
append(contentsOf: data)
5667
}

Sources/SwiftProtobuf/BinaryEncodingVisitor.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,8 @@ internal struct BinaryEncodingVisitor: Visitor {
2727
/// - Precondition: `pointer` must point to an allocated block of memory that
2828
/// is large enough to hold the entire encoded message. For performance
2929
/// reasons, the encoder does not make any attempts to verify this.
30-
init(forWritingInto pointer: UnsafeMutableRawPointer, options: BinaryEncodingOptions) {
31-
self.encoder = BinaryEncoder(forWritingInto: pointer)
30+
init(forWritingInto buffer: UnsafeMutableRawBufferPointer, options: BinaryEncodingOptions) {
31+
self.encoder = BinaryEncoder(forWritingInto: buffer)
3232
self.options = options
3333
}
3434

@@ -374,10 +374,10 @@ extension BinaryEncodingVisitor {
374374
encoder.putVarInt(value: length)
375375
// Create the sub encoder after writing the length.
376376
var subVisitor = BinaryEncodingVisitor(
377-
forWritingInto: encoder.pointer, options: options
377+
forWritingInto: encoder.remainder, options: options
378378
)
379379
try value.traverse(visitor: &subVisitor)
380-
encoder.pointer = subVisitor.encoder.pointer
380+
encoder.advance(subVisitor.encoder.used)
381381

382382
encoder.putVarInt(value: Int64(WireFormat.MessageSet.Tags.itemEnd.rawValue))
383383
}

Sources/SwiftProtobuf/Message+BinaryAdditions.swift

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -53,13 +53,11 @@ extension Message {
5353

5454
var data = Bytes(repeating: 0, count: requiredSize)
5555
try data.withUnsafeMutableBytes { (body: UnsafeMutableRawBufferPointer) in
56-
if let baseAddress = body.baseAddress, body.count > 0 {
57-
var visitor = BinaryEncodingVisitor(forWritingInto: baseAddress, options: options)
58-
try traverse(visitor: &visitor)
59-
// Currently not exposing this from the api because it really would be
60-
// an internal error in the library and should never happen.
61-
assert(requiredSize == visitor.encoder.distance(pointer: baseAddress))
62-
}
56+
var visitor = BinaryEncodingVisitor(forWritingInto: body, options: options)
57+
try traverse(visitor: &visitor)
58+
// Currently not exposing this from the api because it really would be
59+
// an internal error in the library and should never happen.
60+
assert(visitor.encoder.remainder.count == 0)
6361
}
6462
return data
6563
}

0 commit comments

Comments
 (0)