Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
38 changes: 24 additions & 14 deletions Sources/NIOCore/ByteBuffer-aux.swift
Original file line number Diff line number Diff line change
Expand Up @@ -426,8 +426,12 @@ extension ByteBuffer {
/// - Returns: The number of bytes read.
@discardableResult
@inlinable
public mutating func readWithUnsafeReadableBytes(_ body: (UnsafeRawBufferPointer) throws -> Int) rethrows -> Int {
let bytesRead = try self.withUnsafeReadableBytes({ try body($0) })
public mutating func readWithUnsafeReadableBytes<ErrorType: Error>(
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

NIT: In many other places the generic type is called Failure but not too important

_ body: (UnsafeRawBufferPointer) throws(ErrorType) -> Int
) throws(ErrorType) -> Int {
let bytesRead = try self.withUnsafeReadableBytes({ (ptr: UnsafeRawBufferPointer) throws(ErrorType) -> Int in
try body(ptr)
})
self._moveReaderIndex(forwardBy: bytesRead)
return bytesRead
}
Expand All @@ -442,10 +446,12 @@ extension ByteBuffer {
/// - Returns: The number of bytes read.
@discardableResult
@inlinable
public mutating func readWithUnsafeMutableReadableBytes(
_ body: (UnsafeMutableRawBufferPointer) throws -> Int
) rethrows -> Int {
let bytesRead = try self.withUnsafeMutableReadableBytes({ try body($0) })
public mutating func readWithUnsafeMutableReadableBytes<ErrorType: Error>(
_ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> Int
) throws(ErrorType) -> Int {
let bytesRead = try self.withUnsafeMutableReadableBytes({
(ptr: UnsafeMutableRawBufferPointer) throws(ErrorType) -> Int in try body(ptr)
})
self._moveReaderIndex(forwardBy: bytesRead)
return bytesRead
}
Expand Down Expand Up @@ -619,10 +625,12 @@ extension ByteBuffer {
/// - body: The closure that will accept the yielded bytes and returns the number of bytes it processed along with some other value.
/// - Returns: The value `body` returned in the second tuple component.
@inlinable
public mutating func readWithUnsafeMutableReadableBytes<T>(
_ body: (UnsafeMutableRawBufferPointer) throws -> (Int, T)
) rethrows -> T {
let (bytesRead, ret) = try self.withUnsafeMutableReadableBytes({ try body($0) })
public mutating func readWithUnsafeMutableReadableBytes<T, ErrorType: Error>(
_ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> (Int, T)
) throws(ErrorType) -> T {
let (bytesRead, ret) = try self.withUnsafeMutableReadableBytes({
(ptr: UnsafeMutableRawBufferPointer) throws(ErrorType) -> (Int, T) in try body(ptr)
})
self._moveReaderIndex(forwardBy: bytesRead)
return ret
}
Expand All @@ -636,10 +644,12 @@ extension ByteBuffer {
/// - body: The closure that will accept the yielded bytes and returns the number of bytes it processed along with some other value.
/// - Returns: The value `body` returned in the second tuple component.
@inlinable
public mutating func readWithUnsafeReadableBytes<T>(
_ body: (UnsafeRawBufferPointer) throws -> (Int, T)
) rethrows -> T {
let (bytesRead, ret) = try self.withUnsafeReadableBytes({ try body($0) })
public mutating func readWithUnsafeReadableBytes<T, ErrorType: Error>(
_ body: (UnsafeRawBufferPointer) throws(ErrorType) -> (Int, T)
) throws(ErrorType) -> T {
let (bytesRead, ret) = try self.withUnsafeReadableBytes({
(ptr: UnsafeRawBufferPointer) throws(ErrorType) -> (Int, T) in try body(ptr)
})
self._moveReaderIndex(forwardBy: bytesRead)
return ret
}
Expand Down
6 changes: 3 additions & 3 deletions Sources/NIOCore/ByteBuffer-binaryEncodedLengthPrefix.swift
Original file line number Diff line number Diff line change
Expand Up @@ -116,10 +116,10 @@ extension ByteBuffer {
/// - Returns: Number of total bytes written. This is the length of the written data + the number of bytes used to write the length before it.
@discardableResult
@inlinable
public mutating func writeLengthPrefixed<Strategy: NIOBinaryIntegerEncodingStrategy>(
public mutating func writeLengthPrefixed<Strategy: NIOBinaryIntegerEncodingStrategy, ErrorType: Error>(
strategy: Strategy,
writeData: (_ buffer: inout ByteBuffer) throws -> Int
) rethrows -> Int {
writeData: (_ buffer: inout ByteBuffer) throws(ErrorType) -> Int
) throws(ErrorType) -> Int {
/// The index at which we write the length
let lengthPrefixIndex = self.writerIndex
/// The space which we reserve for writing the length
Expand Down
63 changes: 37 additions & 26 deletions Sources/NIOCore/ByteBuffer-core.swift
Original file line number Diff line number Diff line change
Expand Up @@ -682,9 +682,9 @@ public struct ByteBuffer {
/// - body: The closure that will accept the yielded bytes.
/// - Returns: The value returned by `body`.
@inlinable
public mutating func withUnsafeMutableReadableBytes<T>(
_ body: (UnsafeMutableRawBufferPointer) throws -> T
) rethrows -> T {
public mutating func withUnsafeMutableReadableBytes<T, ErrorType: Error>(
_ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> T
) throws(ErrorType) -> T {
self._copyStorageAndRebaseIfNeeded()
// this is safe because we always know that readerIndex >= writerIndex
let range = Range<Int>(uncheckedBounds: (lower: self.readerIndex, upper: self.writerIndex))
Expand All @@ -702,9 +702,9 @@ public struct ByteBuffer {
/// - body: The closure that will accept the yielded bytes and return the number of bytes written.
/// - Returns: The number of bytes written.
@inlinable
public mutating func withUnsafeMutableWritableBytes<T>(
_ body: (UnsafeMutableRawBufferPointer) throws -> T
) rethrows -> T {
public mutating func withUnsafeMutableWritableBytes<T, ErrorType: Error>(
_ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> T
) throws(ErrorType) -> T {
self._copyStorageAndRebaseIfNeeded()
return try body(.init(rebasing: self._slicedStorageBuffer.dropFirst(self.writerIndex)))
}
Expand All @@ -719,14 +719,16 @@ public struct ByteBuffer {
/// - Returns: The number of bytes written.
@discardableResult
@inlinable
public mutating func writeWithUnsafeMutableBytes(
public mutating func writeWithUnsafeMutableBytes<ErrorType: Error>(
minimumWritableBytes: Int,
_ body: (UnsafeMutableRawBufferPointer) throws -> Int
) rethrows -> Int {
_ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> Int
) throws(ErrorType) -> Int {
if minimumWritableBytes > 0 {
self.reserveCapacity(minimumWritableBytes: minimumWritableBytes)
}
let bytesWritten = try self.withUnsafeMutableWritableBytes({ try body($0) })
let bytesWritten = try self.withUnsafeMutableWritableBytes({
(ptr: UnsafeMutableRawBufferPointer) throws(ErrorType) -> Int in try body(ptr)
})
self._moveWriterIndex(to: self._writerIndex + _toIndex(bytesWritten))
return bytesWritten
}
Expand All @@ -739,18 +741,23 @@ public struct ByteBuffer {
)
@discardableResult
@inlinable
public mutating func writeWithUnsafeMutableBytes(
_ body: (UnsafeMutableRawBufferPointer) throws -> Int
) rethrows -> Int {
try self.writeWithUnsafeMutableBytes(minimumWritableBytes: 0, { try body($0) })
public mutating func writeWithUnsafeMutableBytes<ErrorType: Error>(
_ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> Int
) throws(ErrorType) -> Int {
try self.writeWithUnsafeMutableBytes(
minimumWritableBytes: 0,
{ (ptr: UnsafeMutableRawBufferPointer) throws(ErrorType) -> Int in try body(ptr) }
)
}

/// This vends a pointer to the storage of the `ByteBuffer`. It's marked as _very unsafe_ because it might contain
/// uninitialised memory and it's undefined behaviour to read it. In most cases you should use `withUnsafeReadableBytes`.
///
/// - warning: Do not escape the pointer from the closure for later use.
@inlinable
public func withVeryUnsafeBytes<T>(_ body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T {
public func withVeryUnsafeBytes<T, ErrorType: Error>(
_ body: (UnsafeRawBufferPointer) throws(ErrorType) -> T
) throws(ErrorType) -> T {
try body(.init(self._slicedStorageBuffer))
}

Expand All @@ -759,9 +766,9 @@ public struct ByteBuffer {
///
/// - warning: Do not escape the pointer from the closure for later use.
@inlinable
public mutating func withVeryUnsafeMutableBytes<T>(
_ body: (UnsafeMutableRawBufferPointer) throws -> T
) rethrows -> T {
public mutating func withVeryUnsafeMutableBytes<T, ErrorType: Error>(
_ body: (UnsafeMutableRawBufferPointer) throws(ErrorType) -> T
) throws(ErrorType) -> T {
self._copyStorageAndRebaseIfNeeded() // this will trigger a CoW if necessary
return try body(.init(self._slicedStorageBuffer))
}
Expand All @@ -774,7 +781,9 @@ public struct ByteBuffer {
/// - body: The closure that will accept the yielded bytes.
/// - Returns: The value returned by `body`.
@inlinable
public func withUnsafeReadableBytes<T>(_ body: (UnsafeRawBufferPointer) throws -> T) rethrows -> T {
public func withUnsafeReadableBytes<T, ErrorType: Error>(
_ body: (UnsafeRawBufferPointer) throws(ErrorType) -> T
) throws(ErrorType) -> T {
// This is safe, writerIndex >= readerIndex
let range = Range<Int>(uncheckedBounds: (lower: self.readerIndex, upper: self.writerIndex))
return try body(.init(rebasing: self._slicedStorageBuffer[range]))
Expand All @@ -792,9 +801,9 @@ public struct ByteBuffer {
/// - body: The closure that will accept the yielded bytes and the `storageManagement`.
/// - Returns: The value returned by `body`.
@inlinable
public func withUnsafeReadableBytesWithStorageManagement<T>(
_ body: (UnsafeRawBufferPointer, Unmanaged<AnyObject>) throws -> T
) rethrows -> T {
public func withUnsafeReadableBytesWithStorageManagement<T, ErrorType: Error>(
_ body: (UnsafeRawBufferPointer, Unmanaged<AnyObject>) throws(ErrorType) -> T
) throws(ErrorType) -> T {
let storageReference: Unmanaged<AnyObject> = Unmanaged.passUnretained(self._storage)
// This is safe, writerIndex >= readerIndex
let range = Range<Int>(uncheckedBounds: (lower: self.readerIndex, upper: self.writerIndex))
Expand All @@ -803,9 +812,9 @@ public struct ByteBuffer {

/// See `withUnsafeReadableBytesWithStorageManagement` and `withVeryUnsafeBytes`.
@inlinable
public func withVeryUnsafeBytesWithStorageManagement<T>(
_ body: (UnsafeRawBufferPointer, Unmanaged<AnyObject>) throws -> T
) rethrows -> T {
public func withVeryUnsafeBytesWithStorageManagement<T, ErrorType: Error>(
_ body: (UnsafeRawBufferPointer, Unmanaged<AnyObject>) throws(ErrorType) -> T
) throws(ErrorType) -> T {
let storageReference: Unmanaged<AnyObject> = Unmanaged.passUnretained(self._storage)
return try body(.init(self._slicedStorageBuffer), storageReference)
}
Expand Down Expand Up @@ -1257,7 +1266,9 @@ extension ByteBuffer {
/// - body: The modification operation to execute, with this `ByteBuffer` passed `inout` as an argument.
/// - Returns: The return value of `body`.
@inlinable
public mutating func modifyIfUniquelyOwned<T>(_ body: (inout ByteBuffer) throws -> T) rethrows -> T? {
public mutating func modifyIfUniquelyOwned<T, ErrorType: Error>(
_ body: (inout ByteBuffer) throws(ErrorType) -> T
) throws(ErrorType) -> T? {
if isKnownUniquelyReferenced(&self._storage) {
return try body(&self)
} else {
Expand Down
12 changes: 8 additions & 4 deletions Sources/NIOCore/ByteBuffer-views.swift
Original file line number Diff line number Diff line change
Expand Up @@ -38,8 +38,10 @@ public struct ByteBufferView: RandomAccessCollection, Sendable {
}

@inlinable
public func withUnsafeBytes<R>(_ body: (UnsafeRawBufferPointer) throws -> R) rethrows -> R {
try self._buffer.withVeryUnsafeBytes { ptr in
public func withUnsafeBytes<R, ErrorType: Error>(
_ body: (UnsafeRawBufferPointer) throws(ErrorType) -> R
) throws(ErrorType) -> R {
try self._buffer.withVeryUnsafeBytes { (ptr: UnsafeRawBufferPointer) throws(ErrorType) -> R in
try body(
UnsafeRawBufferPointer(
start: ptr.baseAddress!.advanced(by: self._range.lowerBound),
Expand Down Expand Up @@ -98,8 +100,10 @@ public struct ByteBufferView: RandomAccessCollection, Sendable {
}

@inlinable
public func withContiguousStorageIfAvailable<R>(_ body: (UnsafeBufferPointer<UInt8>) throws -> R) rethrows -> R? {
try self.withUnsafeBytes { bytes in
public func withContiguousStorageIfAvailable<R, ErrorType: Error>(
_ body: (UnsafeBufferPointer<UInt8>) throws(ErrorType) -> R
) throws(ErrorType) -> R? {
try self.withUnsafeBytes { (bytes: UnsafeRawBufferPointer) throws(ErrorType) -> R in
try body(bytes.bindMemory(to: UInt8.self))
}
}
Expand Down
6 changes: 3 additions & 3 deletions Sources/NIOCore/Docs.docc/ByteBuffer-lengthPrefix.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,10 +56,10 @@ We decided to add the following API to ByteBuffer:
/// - strategy: The strategy to use for encoding the length.
/// - writeData: A closure that takes a buffer, writes some data to it, and returns the number of bytes written.
/// - Returns: Number of total bytes written. This is the length of the written data + the number of bytes used to write the length before it.
public mutating func writeLengthPrefixed<Strategy: NIOBinaryIntegerEncodingStrategy>(
public mutating func writeLengthPrefixed<Strategy: NIOBinaryIntegerEncodingStrategy, ErrorType: Error>(
strategy: Strategy,
writeData: (_ buffer: inout ByteBuffer) throws -> Int
) rethrows -> Int
writeData: (_ buffer: inout ByteBuffer) throws(ErrorType) -> Int
) throws(ErrorType) -> Int
```

Users could use the function as follows:
Expand Down
Loading