From bf0eed03d91fb52503950f8ca187bf4b18f2b7cc Mon Sep 17 00:00:00 2001 From: Steffan Andrews Date: Thu, 18 Aug 2022 01:04:50 -0700 Subject: [PATCH] `PassiveDataReader`: Now uses throws instead of returning Optionals --- .../Abstractions/PassiveDataReader.swift | 34 +++-- .../PassiveDataReader Tests.swift | 116 +++++++++--------- 2 files changed, 79 insertions(+), 71 deletions(-) diff --git a/Sources/OTCore/Abstractions/PassiveDataReader.swift b/Sources/OTCore/Abstractions/PassiveDataReader.swift index 75c038b..d0c71b8 100644 --- a/Sources/OTCore/Abstractions/PassiveDataReader.swift +++ b/Sources/OTCore/Abstractions/PassiveDataReader.swift @@ -53,16 +53,16 @@ public struct PassiveDataReader { /// Return the next byte and increment the read offset. /// /// If no bytes remain, `nil` will be returned. - public mutating func readByte() -> D.Element? { - guard let d = dataByte() else { return nil } + public mutating func readByte() throws -> D.Element { + let d = try dataByte() defer { readOffset += 1 } return d } /// Read the next byte without advancing the read offset. /// If no bytes remain, `nil` will be returned. - public func nonAdvancingReadByte() -> D.Element? { - dataByte() + public func nonAdvancingReadByte() throws -> D.Element { + try dataByte() } /// Return the next _n_ number of bytes and increment the read offset. @@ -70,8 +70,8 @@ public struct PassiveDataReader { /// If `bytes` parameter is nil, the remainder of the data will be returned. /// /// If fewer bytes remain than are requested, `nil` will be returned. - public mutating func read(bytes count: Int? = nil) -> D.SubSequence? { - guard let d = data(bytes: count) else { return nil } + public mutating func read(bytes count: Int? = nil) throws -> D.SubSequence { + let d = try data(bytes: count) defer { readOffset += d.advanceCount } return d.data } @@ -79,8 +79,8 @@ public struct PassiveDataReader { /// Read _n_ number of bytes from the current read offset, without advancing the read offset. /// If `bytes count` passed is `nil`, the remainder of the data will be returned. /// If fewer bytes remain than are requested, `nil` will be returned. - public func nonAdvancingRead(bytes count: Int? = nil) -> D.SubSequence? { - data(bytes: count)?.data + public func nonAdvancingRead(bytes count: Int? = nil) throws -> D.SubSequence { + try data(bytes: count).data } // MARK: - Internal @@ -91,19 +91,19 @@ public struct PassiveDataReader { return out } - func dataByte() -> D.Element? { - guard remainingByteCount > 0 else { return nil } + func dataByte() throws -> D.Element { + guard remainingByteCount > 0 else { throw ReadError.pastEndOfStream } let readPosIndex = withData { $0.index($0.startIndex, offsetBy: readOffset) } return withData { $0[readPosIndex] } } - func data(bytes count: Int? = nil) -> (data: D.SubSequence, advanceCount: Int)? { + func data(bytes count: Int? = nil) throws -> (data: D.SubSequence, advanceCount: Int) { if count == 0 { return (data: withData { $0[$0.startIndex ..< $0.startIndex] }, advanceCount: 0) } if let count = count, - count < 0 { return nil } + count < 0 { throw ReadError.invalidByteCount } let readPosStartIndex = withData { $0.index($0.startIndex, offsetBy: readOffset) } @@ -113,7 +113,7 @@ public struct PassiveDataReader { guard withData({ $0.indices.contains(readPosStartIndex) && $0.indices.contains(endIndex) - }) else { return nil } + }) else { throw ReadError.pastEndOfStream } let returnBytes = withData { $0[readPosStartIndex ... endIndex] } @@ -121,6 +121,14 @@ public struct PassiveDataReader { } } +extension PassiveDataReader { + /// Error returned by `PassiveDataReader` methods. + public enum ReadError: Error { + case pastEndOfStream + case invalidByteCount + } +} + extension DataProtocol { /// **OTCore:** /// Accesses the data by providing a `PassiveDataReader` instance to a closure. diff --git a/Tests/OTCoreTests/Abstractions/PassiveDataReader Tests.swift b/Tests/OTCoreTests/Abstractions/PassiveDataReader Tests.swift index 2d526a4..22bb9a9 100644 --- a/Tests/OTCoreTests/Abstractions/PassiveDataReader Tests.swift +++ b/Tests/OTCoreTests/Abstractions/PassiveDataReader Tests.swift @@ -21,15 +21,15 @@ class Abstractions_PassiveDataReader_Tests: XCTestCase { XCTAssertEqual(dr.readOffset, 0) XCTAssertEqual(dr.remainingByteCount, 4) - XCTAssertEqual(dr.read(bytes: 1), Data([0x01])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x01])) XCTAssertEqual(dr.remainingByteCount, 3) - XCTAssertEqual(dr.read(bytes: 1), Data([0x02])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x02])) XCTAssertEqual(dr.remainingByteCount, 2) - XCTAssertEqual(dr.read(bytes: 1), Data([0x03])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x03])) XCTAssertEqual(dr.remainingByteCount, 1) - XCTAssertEqual(dr.read(bytes: 1), Data([0x04])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x04])) XCTAssertEqual(dr.remainingByteCount, 0) - XCTAssertEqual(dr.read(bytes: 1), nil) + XCTAssertThrowsError(try dr.read(bytes: 1)) XCTAssertEqual(dr.remainingByteCount, 0) } @@ -39,15 +39,15 @@ class Abstractions_PassiveDataReader_Tests: XCTestCase { XCTAssertEqual(dr.readOffset, 0) XCTAssertEqual(dr.remainingByteCount, 4) - XCTAssertEqual(dr.readByte(), 0x01) + XCTAssertEqual(try dr.readByte(), 0x01) XCTAssertEqual(dr.remainingByteCount, 3) - XCTAssertEqual(dr.readByte(), 0x02) + XCTAssertEqual(try dr.readByte(), 0x02) XCTAssertEqual(dr.remainingByteCount, 2) - XCTAssertEqual(dr.readByte(), 0x03) + XCTAssertEqual(try dr.readByte(), 0x03) XCTAssertEqual(dr.remainingByteCount, 1) - XCTAssertEqual(dr.readByte(), 0x04) + XCTAssertEqual(try dr.readByte(), 0x04) XCTAssertEqual(dr.remainingByteCount, 0) - XCTAssertEqual(dr.readByte(), nil) + XCTAssertThrowsError(try dr.readByte()) XCTAssertEqual(dr.remainingByteCount, 0) } @@ -55,22 +55,22 @@ class Abstractions_PassiveDataReader_Tests: XCTestCase { do { var dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.read(), data) - XCTAssertEqual(dr.read(bytes: 1), nil) + XCTAssertEqual(try dr.read(), data) + XCTAssertThrowsError(try dr.read(bytes: 1)) } // .read - zero count read - return empty data, not nil do { var dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.read(bytes: 0), Data()) + XCTAssertEqual(try dr.read(bytes: 0), Data()) } // .read - read overflow - return nil do { var dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.read(bytes: 5), nil) + XCTAssertThrowsError(try dr.read(bytes: 5)) } } @@ -81,34 +81,34 @@ class Abstractions_PassiveDataReader_Tests: XCTestCase { do { var dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.nonAdvancingRead(), data) - XCTAssertEqual(dr.read(bytes: 1), Data([0x01])) + XCTAssertEqual(try dr.nonAdvancingRead(), data) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x01])) } // single bytes do { var dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.nonAdvancingReadByte(), data[0]) - XCTAssertEqual(dr.nonAdvancingReadByte(), data[0]) - XCTAssertEqual(dr.readByte(), data[0]) - XCTAssertEqual(dr.readByte(), data[1]) + XCTAssertEqual(try dr.nonAdvancingReadByte(), data[0]) + XCTAssertEqual(try dr.nonAdvancingReadByte(), data[0]) + XCTAssertEqual(try dr.readByte(), data[0]) + XCTAssertEqual(try dr.readByte(), data[1]) } // .nonAdvancingRead - read byte counts do { let dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.nonAdvancingRead(bytes: 1), Data([0x01])) - XCTAssertEqual(dr.nonAdvancingRead(bytes: 2), Data([0x01, 0x02])) + XCTAssertEqual(try dr.nonAdvancingRead(bytes: 1), Data([0x01])) + XCTAssertEqual(try dr.nonAdvancingRead(bytes: 2), Data([0x01, 0x02])) } // .nonAdvancingRead - read overflow - return nil do { var dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.nonAdvancingRead(bytes: 5), nil) - XCTAssertEqual(dr.read(bytes: 1), Data([0x01])) + XCTAssertThrowsError(try dr.nonAdvancingRead(bytes: 5)) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x01])) } } @@ -120,7 +120,7 @@ class Abstractions_PassiveDataReader_Tests: XCTestCase { var dr = PassiveDataReader { $0(&data) } dr.advanceBy(1) - XCTAssertEqual(dr.read(bytes: 1), Data([0x02])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x02])) } } @@ -131,10 +131,10 @@ class Abstractions_PassiveDataReader_Tests: XCTestCase { do { var dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.read(bytes: 1), Data([0x01])) - XCTAssertEqual(dr.read(bytes: 2), Data([0x02, 0x03])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x01])) + XCTAssertEqual(try dr.read(bytes: 2), Data([0x02, 0x03])) dr.reset() - XCTAssertEqual(dr.read(bytes: 1), Data([0x01])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x01])) } } @@ -145,14 +145,14 @@ class Abstractions_PassiveDataReader_Tests: XCTestCase { var dr = PassiveDataReader { $0(&data) } XCTAssertEqual(dr.readOffset, 0) - XCTAssertEqual(dr.read(bytes: 1), Data([0x01])) - XCTAssertEqual(dr.read(bytes: 1), Data([0x02])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x01])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x02])) data = Data([0x0A, 0x0B, 0x0C, 0x0D]) - XCTAssertEqual(dr.read(bytes: 1), Data([0x0C])) - XCTAssertEqual(dr.read(bytes: 1), Data([0x0D])) - XCTAssertEqual(dr.read(bytes: 1), nil) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x0C])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x0D])) + XCTAssertThrowsError(try dr.read(bytes: 1)) } // MARK: - Data storage starting with index >0 @@ -174,33 +174,33 @@ class Abstractions_PassiveDataReader_Tests: XCTestCase { var dr = PassiveDataReader { $0(&data) } XCTAssertEqual(dr.readOffset, 0) - XCTAssertEqual(dr.read(bytes: 1), Data([0x01])) - XCTAssertEqual(dr.read(bytes: 1), Data([0x02])) - XCTAssertEqual(dr.read(bytes: 1), Data([0x03])) - XCTAssertEqual(dr.read(bytes: 1), Data([0x04])) - XCTAssertEqual(dr.read(bytes: 1), nil) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x01])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x02])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x03])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x04])) + XCTAssertThrowsError(try dr.read(bytes: 1)) } // .read - nil read - return all remaining bytes do { var dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.read(), data) - XCTAssertEqual(dr.read(bytes: 1), nil) + XCTAssertEqual(try dr.read(), data) + XCTAssertThrowsError(try dr.read(bytes: 1)) } // .read - zero count read - return empty data, not nil do { var dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.read(bytes: 0), Data()) + XCTAssertEqual(try dr.read(bytes: 0), Data()) } // .read - read overflow - return nil do { var dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.read(bytes: 5), nil) + XCTAssertThrowsError(try dr.read(bytes: 5)) } } @@ -220,24 +220,24 @@ class Abstractions_PassiveDataReader_Tests: XCTestCase { do { var dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.nonAdvancingRead(), data) - XCTAssertEqual(dr.read(bytes: 1), Data([0x01])) + XCTAssertEqual(try dr.nonAdvancingRead(), data) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x01])) } // .nonAdvancingRead - read byte counts do { let dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.nonAdvancingRead(bytes: 1), Data([0x01])) - XCTAssertEqual(dr.nonAdvancingRead(bytes: 2), Data([0x01, 0x02])) + XCTAssertEqual(try dr.nonAdvancingRead(bytes: 1), Data([0x01])) + XCTAssertEqual(try dr.nonAdvancingRead(bytes: 2), Data([0x01, 0x02])) } // .nonAdvancingRead - read overflow - return nil do { var dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.nonAdvancingRead(bytes: 5), nil) - XCTAssertEqual(dr.read(bytes: 1), Data([0x01])) + XCTAssertThrowsError(try dr.nonAdvancingRead(bytes: 5)) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x01])) } } @@ -258,7 +258,7 @@ class Abstractions_PassiveDataReader_Tests: XCTestCase { var dr = PassiveDataReader { $0(&data) } dr.advanceBy(1) - XCTAssertEqual(dr.read(bytes: 1), Data([0x02])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x02])) } } @@ -278,23 +278,23 @@ class Abstractions_PassiveDataReader_Tests: XCTestCase { do { var dr = PassiveDataReader { $0(&data) } - XCTAssertEqual(dr.read(bytes: 1), Data([0x01])) - XCTAssertEqual(dr.read(bytes: 2), Data([0x02, 0x03])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x01])) + XCTAssertEqual(try dr.read(bytes: 2), Data([0x02, 0x03])) dr.reset() - XCTAssertEqual(dr.read(bytes: 1), Data([0x01])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x01])) } } func testWithDataReader() throws { let data = Data([0x01, 0x02, 0x03, 0x04]) - data.withDataReader { dr in + try data.withDataReader { dr in XCTAssertEqual(dr.readOffset, 0) - XCTAssertEqual(dr.read(bytes: 1), Data([0x01])) - XCTAssertEqual(dr.read(bytes: 1), Data([0x02])) - XCTAssertEqual(dr.read(bytes: 1), Data([0x03])) - XCTAssertEqual(dr.read(bytes: 1), Data([0x04])) - XCTAssertEqual(dr.read(bytes: 1), nil) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x01])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x02])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x03])) + XCTAssertEqual(try dr.read(bytes: 1), Data([0x04])) + XCTAssertThrowsError(try dr.read(bytes: 1)) } struct TestError: Error { }