add witnesses for ByteBufferView.reserveCapacity(_:), append(_:), and append(contentsOf:) (#2309)

* add witnesses for ByteBufferView.reserveCapacity(_:), append(_:), and append(contentsOf:)

* align with project style

* fix incorrect ByteBufferView implementations, add unit tests

* use withUnsafeBytes(of:) instead of CollectionOfOne in ByteBufferView.append(_:)

* address review comments

* Add missing Linux tests

Co-authored-by: Cory Benfield <lukasa@apple.com>
This commit is contained in:
taylorswift 2022-11-14 04:01:25 -06:00 committed by GitHub
parent 558e4f2fb8
commit 75970eb980
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 62 additions and 1 deletions

View File

@ -158,6 +158,36 @@ extension ByteBufferView: RangeReplaceableCollection {
self = ByteBufferView(ByteBuffer()) self = ByteBufferView(ByteBuffer())
} }
/// Reserves enough space in the underlying `ByteBuffer` such that this view can
/// store the specified number of bytes without reallocation.
///
/// See the documentation for ``ByteBuffer.reserveCapacity(_:)`` for more details.
@inlinable
public mutating func reserveCapacity(_ minimumCapacity: Int) {
let additionalCapacity = minimumCapacity - self.count
if additionalCapacity > 0 {
self._buffer.reserveCapacity(self._buffer.capacity + additionalCapacity)
}
}
/// Writes a single byte to the underlying `ByteBuffer`.
@inlinable
public mutating func append(_ byte: UInt8) {
// ``CollectionOfOne`` has no witness for
// ``Sequence.withContiguousStorageIfAvailable(_:)``. so we do this instead:
self._buffer.setInteger(byte, at: self._range.upperBound)
self._range = self._range.lowerBound ..< self._range.upperBound.advanced(by: 1)
self._buffer.moveWriterIndex(to: self._range.upperBound)
}
/// Writes a sequence of bytes to the underlying `ByteBuffer`.
@inlinable
public mutating func append<Bytes: Sequence>(contentsOf bytes: Bytes) where Bytes.Element == UInt8 {
let written = self._buffer.setBytes(bytes, at: self._range.upperBound)
self._range = self._range.lowerBound ..< self._range.upperBound.advanced(by: written)
self._buffer.moveWriterIndex(to: self._range.upperBound)
}
@inlinable @inlinable
public mutating func replaceSubrange<C: Collection>(_ subrange: Range<Index>, with newElements: C) where ByteBufferView.Element == C.Element { public mutating func replaceSubrange<C: Collection>(_ subrange: Range<Index>, with newElements: C) where ByteBufferView.Element == C.Element {
precondition(subrange.startIndex >= self.startIndex && subrange.endIndex <= self.endIndex, precondition(subrange.startIndex >= self.startIndex && subrange.endIndex <= self.endIndex,
@ -193,7 +223,6 @@ extension ByteBufferView: RangeReplaceableCollection {
let additionalByteCount = newElements.count - subrange.count let additionalByteCount = newElements.count - subrange.count
self._buffer.moveWriterIndex(forwardBy: additionalByteCount) self._buffer.moveWriterIndex(forwardBy: additionalByteCount)
self._range = self._range.startIndex ..< self._range.endIndex.advanced(by: additionalByteCount) self._range = self._range.startIndex ..< self._range.endIndex.advanced(by: additionalByteCount)
} }
} }
} }

View File

@ -155,6 +155,8 @@ extension ByteBufferTest {
("testBufferViewReplaceSubrangeWithEqualLengthBytes", testBufferViewReplaceSubrangeWithEqualLengthBytes), ("testBufferViewReplaceSubrangeWithEqualLengthBytes", testBufferViewReplaceSubrangeWithEqualLengthBytes),
("testBufferViewReplaceSubrangeWithFewerBytes", testBufferViewReplaceSubrangeWithFewerBytes), ("testBufferViewReplaceSubrangeWithFewerBytes", testBufferViewReplaceSubrangeWithFewerBytes),
("testBufferViewReplaceSubrangeWithMoreBytes", testBufferViewReplaceSubrangeWithMoreBytes), ("testBufferViewReplaceSubrangeWithMoreBytes", testBufferViewReplaceSubrangeWithMoreBytes),
("testBufferViewAppend", testBufferViewAppend),
("testBufferViewAppendContentsOf", testBufferViewAppendContentsOf),
("testBufferViewEmpty", testBufferViewEmpty), ("testBufferViewEmpty", testBufferViewEmpty),
("testBufferViewFirstIndex", testBufferViewFirstIndex), ("testBufferViewFirstIndex", testBufferViewFirstIndex),
("testBufferViewLastIndex", testBufferViewLastIndex), ("testBufferViewLastIndex", testBufferViewLastIndex),

View File

@ -2019,6 +2019,36 @@ class ByteBufferTest: XCTestCase {
XCTAssertEqual([0x0, 0x1, 0x2, 0xa, 0xb], modifiedBuf.readBytes(length: modifiedBuf.readableBytes)!) XCTAssertEqual([0x0, 0x1, 0x2, 0xa, 0xb], modifiedBuf.readBytes(length: modifiedBuf.readableBytes)!)
} }
func testBufferViewAppend() throws {
self.buf.writeBytes([0x0, 0x1, 0x2, 0x3])
var view = ByteBufferView(self.buf)
XCTAssertTrue(view.elementsEqual([0x0, 0x1, 0x2, 0x3]))
view.append(0xa)
XCTAssertTrue(view.elementsEqual([0x0, 0x1, 0x2, 0x3, 0xa]))
var modifiedBuf = ByteBuffer(view)
XCTAssertEqual(self.buf.readerIndex, modifiedBuf.readerIndex)
XCTAssertEqual(self.buf.writerIndex + 1, modifiedBuf.writerIndex)
XCTAssertEqual([0x0, 0x1, 0x2, 0x3, 0xa], modifiedBuf.readBytes(length: modifiedBuf.readableBytes)!)
}
func testBufferViewAppendContentsOf() throws {
self.buf.writeBytes([0x0, 0x1, 0x2, 0x3])
var view = ByteBufferView(self.buf)
XCTAssertTrue(view.elementsEqual([0x0, 0x1, 0x2, 0x3]))
view.append(contentsOf: [0xa, 0xb])
XCTAssertTrue(view.elementsEqual([0x0, 0x1, 0x2, 0x3, 0xa, 0xb]))
var modifiedBuf = ByteBuffer(view)
XCTAssertEqual(self.buf.readerIndex, modifiedBuf.readerIndex)
XCTAssertEqual(self.buf.writerIndex + 2, modifiedBuf.writerIndex)
XCTAssertEqual([0x0, 0x1, 0x2, 0x3, 0xa, 0xb], modifiedBuf.readBytes(length: modifiedBuf.readableBytes)!)
}
func testBufferViewEmpty() throws { func testBufferViewEmpty() throws {
self.buf.writeBytes([0, 1, 2]) self.buf.writeBytes([0, 1, 2])