From 62e1fbbb6a0d21a89a0eb6ea12e6395799e90aff Mon Sep 17 00:00:00 2001 From: "Devran \"Cosmo\" Uenal" Date: Thu, 26 Sep 2019 06:56:23 +0200 Subject: [PATCH 01/13] Rename getCharacter to readCharacter as it is incrementing the bitCursor --- Sources/BinaryKit/BinaryKit.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/BinaryKit/BinaryKit.swift b/Sources/BinaryKit/BinaryKit.swift index f798ad1..e8ad2bd 100644 --- a/Sources/BinaryKit/BinaryKit.swift +++ b/Sources/BinaryKit/BinaryKit.swift @@ -124,7 +124,8 @@ public struct Binary { return result } - public mutating func getCharacter() throws -> Character { + // MARK: - Character + public mutating func readCharacter() throws -> Character { return Character(UnicodeScalar(try readByte())) } From 3ed44fd0c6332822fbbef4b1857a8b0139bb84fc Mon Sep 17 00:00:00 2001 From: "Devran \"Cosmo\" Uenal" Date: Thu, 26 Sep 2019 18:21:43 +0200 Subject: [PATCH 02/13] Replace "magic number" --- Sources/BinaryKit/BinaryKit.swift | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Sources/BinaryKit/BinaryKit.swift b/Sources/BinaryKit/BinaryKit.swift index e8ad2bd..0d19b85 100644 --- a/Sources/BinaryKit/BinaryKit.swift +++ b/Sources/BinaryKit/BinaryKit.swift @@ -8,7 +8,8 @@ enum BinError: Error { public struct Binary { private var bitCursor: Int var bytesStore: [UInt8] - private let byteSize = 8 + + private let byteSize = UInt8.bitWidth public init(bytes: [UInt8]) { self.bitCursor = 0 From 60e37614f329b7ba44624b05aaad67dd2d4b18cd Mon Sep 17 00:00:00 2001 From: "Devran \"Cosmo\" Uenal" Date: Thu, 26 Sep 2019 18:21:57 +0200 Subject: [PATCH 03/13] Explain the properties --- Sources/BinaryKit/BinaryKit.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Sources/BinaryKit/BinaryKit.swift b/Sources/BinaryKit/BinaryKit.swift index 0d19b85..8df1d8e 100644 --- a/Sources/BinaryKit/BinaryKit.swift +++ b/Sources/BinaryKit/BinaryKit.swift @@ -6,7 +6,11 @@ enum BinError: Error { } public struct Binary { + /// Stores a reading cursor in bits. + /// All methods starting with `read` will increment the value of `bitCursor`. private var bitCursor: Int + + /// Stores the binary content. var bytesStore: [UInt8] private let byteSize = UInt8.bitWidth From c7d53b8550d57d773e780fdd80abdcdefbff7844 Mon Sep 17 00:00:00 2001 From: "Devran \"Cosmo\" Uenal" Date: Thu, 26 Sep 2019 18:22:19 +0200 Subject: [PATCH 04/13] Add mutating functions to increment the cursor --- Sources/BinaryKit/BinaryKit.swift | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/Sources/BinaryKit/BinaryKit.swift b/Sources/BinaryKit/BinaryKit.swift index 8df1d8e..b4e56ca 100644 --- a/Sources/BinaryKit/BinaryKit.swift +++ b/Sources/BinaryKit/BinaryKit.swift @@ -41,6 +41,16 @@ public struct Binary { return bitCursor + (bytes * byteSize) } + /// Increments the `bitCursor`-value by the given `bits`. + private mutating func incrementCursorBy(bits: Int) { + bitCursor = incrementedCursorBy(bits: bits) + } + + /// Increments the `bitCursor`-value by the given `bytes`. + private mutating func incrementCursorBy(bytes: Int) { + bitCursor = incrementedCursorBy(bytes: bytes) + } + /// Sets the reading cursor back to its initial value. public mutating func resetCursor() { self.bitCursor = 0 From 26a5386559d3c94fafc69a5959123a858f097bf8 Mon Sep 17 00:00:00 2001 From: "Devran \"Cosmo\" Uenal" Date: Thu, 26 Sep 2019 18:22:50 +0200 Subject: [PATCH 05/13] Update comments text --- Sources/BinaryKit/BinaryKit.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Sources/BinaryKit/BinaryKit.swift b/Sources/BinaryKit/BinaryKit.swift index b4e56ca..3246252 100644 --- a/Sources/BinaryKit/BinaryKit.swift +++ b/Sources/BinaryKit/BinaryKit.swift @@ -58,7 +58,7 @@ public struct Binary { // MARK: - Bit - /// Returns the binary value `0` or `1` of the given position. + /// Returns an `UInt8` with the value of 0 or 1 of the given position. public func getBit(index: Int) throws -> UInt8 { guard (0..<(bytesStore.count)).contains(index / byteSize) else { throw BinError.outOfBounds @@ -78,8 +78,8 @@ public struct Binary { } } - /// Returns the binary value `0` or `1` of the given position and - /// increments the reading cursor by one bit. + /// Returns an `UInt8` with the value of 0 or 1 of the given + /// position and increments the reading cursor by one bit. public mutating func readBit() throws -> UInt8 { defer { bitCursor = incrementedCursorBy(bits: 1) } return try getBit(index: bitCursor) From af475633432e39211254c1e49963c140fc5d4a7e Mon Sep 17 00:00:00 2001 From: "Devran \"Cosmo\" Uenal" Date: Thu, 26 Sep 2019 18:23:31 +0200 Subject: [PATCH 06/13] Increment cursor with new mutating methods --- Sources/BinaryKit/BinaryKit.swift | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/Sources/BinaryKit/BinaryKit.swift b/Sources/BinaryKit/BinaryKit.swift index 3246252..7d5a1cd 100644 --- a/Sources/BinaryKit/BinaryKit.swift +++ b/Sources/BinaryKit/BinaryKit.swift @@ -81,8 +81,9 @@ public struct Binary { /// Returns an `UInt8` with the value of 0 or 1 of the given /// position and increments the reading cursor by one bit. public mutating func readBit() throws -> UInt8 { - defer { bitCursor = incrementedCursorBy(bits: 1) } - return try getBit(index: bitCursor) + let result = try getBit(index: bitCursor) + incrementCursorBy(bits: 1) + return result } /// Returns the `Int`-value of the next n-bits (`quantitiy`) @@ -91,10 +92,11 @@ public struct Binary { guard (0...(bytesStore.count * byteSize)).contains(bitCursor + quantitiy) else { throw BinError.outOfBounds } - defer { bitCursor = incrementedCursorBy(bits: quantitiy) } - return try (bitCursor..<(bitCursor + quantitiy)).reversed().enumerated().reduce(0) { + let result = try (bitCursor..<(bitCursor + quantitiy)).reversed().enumerated().reduce(0) { $0 + Int(try getBit(index: $1.element) << $1.offset) } + incrementCursorBy(bits: quantitiy) + return result } // MARK: - Byte @@ -119,7 +121,7 @@ public struct Binary { /// Returns the `UInt8`-value of the next byte and increments the reading cursor. public mutating func readByte() throws -> UInt8 { let result = try getByte(index: bitCursor / byteSize) - bitCursor = incrementedCursorBy(bytes: 1) + incrementCursorBy(bytes: 1) return result } @@ -127,11 +129,12 @@ public struct Binary { /// increments the reading cursor by n-bytes. public mutating func readBytes(quantitiy: Int) throws -> [UInt8] { let byteCursor = bitCursor / byteSize - defer { bitCursor = incrementedCursorBy(bytes: quantitiy) } + incrementCursorBy(bytes: quantitiy) return try getBytes(range: byteCursor..<(byteCursor + quantitiy)) } - // MARK: - String + // MARK: - Read Other + public mutating func readString(quantitiyOfBytes quantitiy: Int, encoding: String.Encoding = .utf8) throws -> String { guard let result = String(bytes: try self.readBytes(quantitiy: quantitiy), encoding: encoding) else { throw BinError.notString @@ -139,7 +142,6 @@ public struct Binary { return result } - // MARK: - Character public mutating func readCharacter() throws -> Character { return Character(UnicodeScalar(try readByte())) } From 049a422736e4edff1cdb78d8e3747c540644cc72 Mon Sep 17 00:00:00 2001 From: "Devran \"Cosmo\" Uenal" Date: Thu, 26 Sep 2019 18:23:45 +0200 Subject: [PATCH 07/13] Add readNibble() --- Sources/BinaryKit/BinaryKit.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Sources/BinaryKit/BinaryKit.swift b/Sources/BinaryKit/BinaryKit.swift index 7d5a1cd..42803fd 100644 --- a/Sources/BinaryKit/BinaryKit.swift +++ b/Sources/BinaryKit/BinaryKit.swift @@ -149,4 +149,8 @@ public struct Binary { public mutating func readBool() throws -> Bool { return try readBit() == 1 } + + public mutating func readNibble() throws -> UInt8 { + return UInt8(try readBits(quantitiy: 4)) + } } From 39b5ada77a2998833940c682c1d9b99803515b88 Mon Sep 17 00:00:00 2001 From: "Devran \"Cosmo\" Uenal" Date: Thu, 26 Sep 2019 18:24:18 +0200 Subject: [PATCH 08/13] Add methods to search for indices by byte array or string --- Sources/BinaryKit/BinaryKit.swift | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/Sources/BinaryKit/BinaryKit.swift b/Sources/BinaryKit/BinaryKit.swift index 42803fd..29bd113 100644 --- a/Sources/BinaryKit/BinaryKit.swift +++ b/Sources/BinaryKit/BinaryKit.swift @@ -153,4 +153,18 @@ public struct Binary { public mutating func readNibble() throws -> UInt8 { return UInt8(try readBits(quantitiy: 4)) } + + // MARK: - Find + + func indices(of sequence: [UInt8]) -> [Int] { + let size = sequence.count + return bytesStore.indices.dropLast(size-1).filter { + bytesStore[$0..<$0+size].elementsEqual(sequence) + } + } + + func indices(of string: String) -> [Int] { + let sequence = [UInt8](string.utf8) + return indices(of: sequence) + } } From 49e08b60738fe927877f68c7db8a7765c274a6ff Mon Sep 17 00:00:00 2001 From: "Devran \"Cosmo\" Uenal" Date: Thu, 26 Sep 2019 18:24:39 +0200 Subject: [PATCH 09/13] Cover code with additional tests --- Tests/BinaryKitTests/BinaryKitTests.swift | 138 ++++++++++++++-------- 1 file changed, 87 insertions(+), 51 deletions(-) diff --git a/Tests/BinaryKitTests/BinaryKitTests.swift b/Tests/BinaryKitTests/BinaryKitTests.swift index b7463aa..1360e0c 100644 --- a/Tests/BinaryKitTests/BinaryKitTests.swift +++ b/Tests/BinaryKitTests/BinaryKitTests.swift @@ -2,49 +2,6 @@ import XCTest @testable import BinaryKit final class BinaryKitTests: XCTestCase { - // MARK: - Byte - - func testByte() { - let bytes: [UInt8] = [0b1010_1101, 0b1010_1111] - var bin = Binary(bytes: bytes) - - XCTAssertEqual(try bin.readByte(), 173) - XCTAssertEqual(try bin.readByte(), 175) - XCTAssertThrowsError(try bin.readByte()) - bin.resetCursor() - XCTAssertEqual(try bin.readByte(), 173) - XCTAssertEqual(try bin.readByte(), 175) - } - - func testByteIndex() { - let bytes: [UInt8] = [0b1010_1101, 0b1010_1111] - let bin = Binary(bytes: bytes) - - XCTAssertThrowsError(try bin.getByte(index: -1)) - XCTAssertEqual(try bin.getByte(index: 0), 173) - XCTAssertEqual(try bin.getByte(index: 1), 175) - XCTAssertThrowsError(try bin.getByte(index: 2)) - } - - func testBytes() { - let bytes: [UInt8] = [0b1010_1101, 0b1010_1111, 0b1000_1101] - var bin = Binary(bytes: bytes) - - XCTAssertEqual(try bin.readBytes(quantitiy: 1), [173]) - XCTAssertEqual(try bin.readBytes(quantitiy: 2), [175, 141]) - XCTAssertThrowsError(try bin.readBytes(quantitiy: 3)) - bin.resetCursor() - XCTAssertEqual(try bin.readBytes(quantitiy: 1), [173]) - } - - func testBytesRange() { - let bytes: [UInt8] = [0b1010_1101, 0b1010_1111] - let bin = Binary(bytes: bytes) - - XCTAssertEqual(try bin.getBytes(range: 0..<2), [173, 175]) - XCTAssertThrowsError(try bin.getBytes(range: 2..<3)) - } - // MARK: - Bit func testBit() { @@ -109,6 +66,49 @@ final class BinaryKitTests: XCTestCase { XCTAssertThrowsError(try bin.getBits(range: 16..<17)) } + // MARK: - Byte + + func testByte() { + let bytes: [UInt8] = [0b1010_1101, 0b1010_1111] + var bin = Binary(bytes: bytes) + + XCTAssertEqual(try bin.readByte(), 173) + XCTAssertEqual(try bin.readByte(), 175) + XCTAssertThrowsError(try bin.readByte()) + bin.resetCursor() + XCTAssertEqual(try bin.readByte(), 173) + XCTAssertEqual(try bin.readByte(), 175) + } + + func testByteIndex() { + let bytes: [UInt8] = [0b1010_1101, 0b1010_1111] + let bin = Binary(bytes: bytes) + + XCTAssertThrowsError(try bin.getByte(index: -1)) + XCTAssertEqual(try bin.getByte(index: 0), 173) + XCTAssertEqual(try bin.getByte(index: 1), 175) + XCTAssertThrowsError(try bin.getByte(index: 2)) + } + + func testBytes() { + let bytes: [UInt8] = [0b1010_1101, 0b1010_1111, 0b1000_1101] + var bin = Binary(bytes: bytes) + + XCTAssertEqual(try bin.readBytes(quantitiy: 1), [173]) + XCTAssertEqual(try bin.readBytes(quantitiy: 2), [175, 141]) + XCTAssertThrowsError(try bin.readBytes(quantitiy: 3)) + bin.resetCursor() + XCTAssertEqual(try bin.readBytes(quantitiy: 1), [173]) + } + + func testBytesRange() { + let bytes: [UInt8] = [0b1010_1101, 0b1010_1111] + let bin = Binary(bytes: bytes) + + XCTAssertEqual(try bin.getBytes(range: 0..<2), [173, 175]) + XCTAssertThrowsError(try bin.getBytes(range: 2..<3)) + } + // MARK: - Init func testHexInit() { @@ -125,26 +125,62 @@ final class BinaryKitTests: XCTestCase { XCTAssertThrowsError(try bin.readByte()) } - // MARK: - Other Readers + // MARK: - Nibble - func testOtherReaders() { - let bytes: [UInt8] = [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33] + func testNibble() { + let bytes: [UInt8] = [0b1010_1101, 0b1010_1111] + var bin = Binary(bytes: bytes) + + XCTAssertEqual(try bin.readNibble(), 10) + XCTAssertEqual(try bin.readNibble(), 13) + } + + // MARK: - String and Character + + func testStringAndCharacter() { + let bytes: [UInt8] = [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33, 0, 255, 0, 100, 0, 9] var bin = Binary(bytes: bytes) XCTAssertEqual(try bin.readString(quantitiyOfBytes: 12), "hello, world") + XCTAssertEqual(try bin.readCharacter(), "!") + XCTAssertThrowsError(try bin.readString(quantitiyOfBytes: 6, encoding: .nonLossyASCII)) + } + + // MARK: - Bool + + func testBool() { + let bytes: [UInt8] = [0b1101_0101] + var bin = Binary(bytes: bytes) + XCTAssertEqual(try bin.readBool(), true) + XCTAssertEqual(try bin.readBool(), true) + XCTAssertEqual(try bin.readBool(), false) + XCTAssertEqual(try bin.readBool(), true) + XCTAssertEqual(try bin.readBool(), false) + } + + // MARK: - Finders + + func testFinders() { + let bytes: [UInt8] = [104, 101, 108, 108, 111, 44, 32, 119, 111, 114, 108, 100, 33] + let bin = Binary(bytes: bytes) + XCTAssertEqual(bin.indices(of: [111, 44]), [4]) + XCTAssertEqual(bin.indices(of: "l"), [2, 3, 10]) + XCTAssertEqual(bin.indices(of: "wo"), [7]) } // MARK: - static var allTests = [ - ("testByte", testByte), - ("testByteIndex", testByteIndex), - ("testBytes", testBytes), - ("testBytesRange", testBytesRange), ("testBitIndex", testBitIndex), ("testBit", testBit), ("testBits", testBits), ("testBitsRange", testBitsRange), + ("testByte", testByte), + ("testByteIndex", testByteIndex), + ("testBytes", testBytes), + ("testBytesRange", testBytesRange), ("testHexInit", testHexInit), - ("testOtherReaders", testOtherReaders), + ("testNibble", testNibble), + ("testStringAndCharacter", testStringAndCharacter), + ("testFinders", testFinders), ] } From ec65cb8fc78ec86d80cde725fbb2d4bdb739bb80 Mon Sep 17 00:00:00 2001 From: "Devran \"Cosmo\" Uenal" Date: Thu, 26 Sep 2019 18:24:41 +0200 Subject: [PATCH 10/13] Update .gitignore --- .gitignore | 90 +++++++----------------------------------------------- 1 file changed, 11 insertions(+), 79 deletions(-) diff --git a/.gitignore b/.gitignore index df439e5..d79485f 100755 --- a/.gitignore +++ b/.gitignore @@ -1,53 +1,5 @@ - -# Created by https://www.gitignore.io/api/macos,swift,xcode,swiftpm,carthage,cocoapods -# Edit at https://www.gitignore.io/?templates=macos,swift,xcode,swiftpm,carthage,cocoapods - -### Carthage ### -# Carthage -# -# Add this line if you want to avoid checking in source code from Carthage dependencies. -# Carthage/Checkouts - -Carthage/Build - -### CocoaPods ### -## CocoaPods GitIgnore Template - -# CocoaPods - Only use to conserve bandwidth / Save time on Pushing -# - Also handy if you have a large number of dependant pods -# - AS PER https://guides.cocoapods.org/using/using-cocoapods.html NEVER IGNORE THE LOCK FILE -Pods/ - -### macOS ### -# General -.DS_Store -.AppleDouble -.LSOverride - -# Icon must end with two \r -Icon - -# Thumbnails -._* - -# Files that might appear in the root of a volume -.DocumentRevisions-V100 -.fseventsd -.Spotlight-V100 -.TemporaryItems -.Trashes -.VolumeIcon.icns -.com.apple.timemachine.donotpresent - -# Directories potentially created on remote AFP share -.AppleDB -.AppleDesktop -Network Trash Folder -Temporary Items -.apdisk - -### Swift ### # Xcode +# # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore ## Build generated @@ -81,32 +33,37 @@ timeline.xctimeline playground.xcworkspace # Swift Package Manager +# # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies. # Packages/ # Package.pins # Package.resolved .build/ -# Add this line if you want to avoid checking in Xcode SPM integration. -# .swiftpm/xcode # CocoaPods +# # We recommend against adding the Pods directory to your .gitignore. However # you should judge for yourself, the pros and cons are mentioned at: # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control +# # Pods/ +# # Add this line if you want to avoid checking in source code from the Xcode workspace # *.xcworkspace # Carthage +# # Add this line if you want to avoid checking in source code from Carthage dependencies. # Carthage/Checkouts +Carthage/Build # Accio dependency management Dependencies/ .accio/ # fastlane +# # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the # screenshots whenever they are needed. # For more information about the recommended setup visit: @@ -118,35 +75,10 @@ fastlane/screenshots/**/*.png fastlane/test_output # Code Injection +# # After new code Injection tools there's a generated folder /iOSInjectionProject # https://github.com/johnno1962/injectionforxcode iOSInjectionProject/ - -### SwiftPM ### -Packages -xcuserdata -*.xcodeproj - - -### Xcode ### -# Xcode -# gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore - -## User settings - -## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9) - -## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4) - -## Xcode Patch -*.xcodeproj/* -!*.xcodeproj/project.pbxproj -!*.xcodeproj/xcshareddata/ -!*.xcworkspace/contents.xcworkspacedata -/*.gcno - -### Xcode Patch ### -**/xcshareddata/WorkspaceSettings.xcsettings - -# End of https://www.gitignore.io/api/macos,swift,xcode,swiftpm,carthage,cocoapods +.DS_Store +.swiftpm From bfb1b0b29d290bb14b822bcb72b46c183e655112 Mon Sep 17 00:00:00 2001 From: "Devran \"Cosmo\" Uenal" Date: Fri, 27 Sep 2019 12:16:39 +0200 Subject: [PATCH 11/13] Improve code documentation --- Sources/BinaryKit/BinaryKit.swift | 71 ++++++++++++++++++++----------- 1 file changed, 45 insertions(+), 26 deletions(-) diff --git a/Sources/BinaryKit/BinaryKit.swift b/Sources/BinaryKit/BinaryKit.swift index 29bd113..0cb3eba 100644 --- a/Sources/BinaryKit/BinaryKit.swift +++ b/Sources/BinaryKit/BinaryKit.swift @@ -13,8 +13,10 @@ public struct Binary { /// Stores the binary content. var bytesStore: [UInt8] + /// Constant with number of bits in a byte (8) private let byteSize = UInt8.bitWidth + /// Initialize a new `Binary`. public init(bytes: [UInt8]) { self.bitCursor = 0 self.bytesStore = bytes @@ -56,7 +58,10 @@ public struct Binary { self.bitCursor = 0 } - // MARK: - Bit + // MARK: - Get + + /// All `get` methods give access to binary data at any given + /// location — without incrementing the internal cursor. /// Returns an `UInt8` with the value of 0 or 1 of the given position. public func getBit(index: Int) throws -> UInt8 { @@ -78,6 +83,30 @@ public struct Binary { } } + /// Returns the `UInt8`-value of the given `index`. + public func getByte(index: Int) throws -> UInt8 { + /// Check if `index` is within bounds of `bytes` + guard (0..<(bytesStore.count)).contains(index) else { + throw BinError.outOfBounds + } + return bytesStore[index] + } + + /// Returns an `[UInt8]` of the given `range`. + public func getBytes(range: Range) throws -> [UInt8] { + guard (0...(bytesStore.count)).contains(range.endIndex) else { + throw BinError.outOfBounds + } + return Array(bytesStore[range]) + } + + // MARK: - Read + + /// All `read*` methods return the next requested binary data + /// and increment an internal cursor (or reading offset) to + /// the end of the requested data, so the + /// next `read*`-method can continue from there. + /// Returns an `UInt8` with the value of 0 or 1 of the given /// position and increments the reading cursor by one bit. public mutating func readBit() throws -> UInt8 { @@ -99,33 +128,15 @@ public struct Binary { return result } - // MARK: - Byte - - /// Returns the `UInt8`-value of the given `index`. - public func getByte(index: Int) throws -> UInt8 { - /// Check if `index` is within bounds of `bytes` - guard (0..<(bytesStore.count)).contains(index) else { - throw BinError.outOfBounds - } - return bytesStore[index] - } - - /// Returns an `[UInt8]` of the given `range`. - public func getBytes(range: Range) throws -> [UInt8] { - guard (0...(bytesStore.count)).contains(range.endIndex) else { - throw BinError.outOfBounds - } - return Array(bytesStore[range]) - } - - /// Returns the `UInt8`-value of the next byte and increments the reading cursor. + /// Returns the `UInt8`-value of the next byte and + /// increments the reading cursor by 1 byte. public mutating func readByte() throws -> UInt8 { let result = try getByte(index: bitCursor / byteSize) incrementCursorBy(bytes: 1) return result } - /// Returns an `[UInt8]` of the next n-bytes (`quantitiy`) and + /// Returns a `[UInt8]` of the next n-bytes (`quantitiy`) and /// increments the reading cursor by n-bytes. public mutating func readBytes(quantitiy: Int) throws -> [UInt8] { let byteCursor = bitCursor / byteSize @@ -133,8 +144,8 @@ public struct Binary { return try getBytes(range: byteCursor..<(byteCursor + quantitiy)) } - // MARK: - Read Other - + /// Returns a `String` of the next n-bytes (`quantitiy`) and + /// increments the reading cursor by n-bytes. public mutating func readString(quantitiyOfBytes quantitiy: Int, encoding: String.Encoding = .utf8) throws -> String { guard let result = String(bytes: try self.readBytes(quantitiy: quantitiy), encoding: encoding) else { throw BinError.notString @@ -142,27 +153,35 @@ public struct Binary { return result } + /// Returns the next byte as `Character` and + /// increments the reading cursor by 1 byte. public mutating func readCharacter() throws -> Character { return Character(UnicodeScalar(try readByte())) } + /// Returns the `Bool`-value of the next bit and + /// increments the reading cursor by 1 bit. public mutating func readBool() throws -> Bool { return try readBit() == 1 } + /// Returns the `UInt8`-value of the next 4 bit and + /// increments the reading cursor by 4 bits. public mutating func readNibble() throws -> UInt8 { return UInt8(try readBits(quantitiy: 4)) } // MARK: - Find + /// Returns indices of given `[UInt8]`. func indices(of sequence: [UInt8]) -> [Int] { let size = sequence.count - return bytesStore.indices.dropLast(size-1).filter { - bytesStore[$0..<$0+size].elementsEqual(sequence) + return bytesStore.indices.dropLast(size - 1).filter { + bytesStore[$0..<($0 + size)].elementsEqual(sequence) } } + /// Returns indices of given `String`. func indices(of string: String) -> [Int] { let sequence = [UInt8](string.utf8) return indices(of: sequence) From 01ca237b0157dea8ff22c46e75fa2008813400ce Mon Sep 17 00:00:00 2001 From: "Devran \"Cosmo\" Uenal" Date: Fri, 27 Sep 2019 12:19:44 +0200 Subject: [PATCH 12/13] Move Error enum into own file --- .../BinaryKit/{BinaryKit.swift => Binary.swift} | 17 ++++++----------- Sources/BinaryKit/BinaryError.swift | 13 +++++++++++++ 2 files changed, 19 insertions(+), 11 deletions(-) rename Sources/BinaryKit/{BinaryKit.swift => Binary.swift} (95%) create mode 100644 Sources/BinaryKit/BinaryError.swift diff --git a/Sources/BinaryKit/BinaryKit.swift b/Sources/BinaryKit/Binary.swift similarity index 95% rename from Sources/BinaryKit/BinaryKit.swift rename to Sources/BinaryKit/Binary.swift index 0cb3eba..c57ef23 100644 --- a/Sources/BinaryKit/BinaryKit.swift +++ b/Sources/BinaryKit/Binary.swift @@ -1,10 +1,5 @@ import Foundation -enum BinError: Error { - case outOfBounds - case notString -} - public struct Binary { /// Stores a reading cursor in bits. /// All methods starting with `read` will increment the value of `bitCursor`. @@ -66,7 +61,7 @@ public struct Binary { /// Returns an `UInt8` with the value of 0 or 1 of the given position. public func getBit(index: Int) throws -> UInt8 { guard (0..<(bytesStore.count)).contains(index / byteSize) else { - throw BinError.outOfBounds + throw BinaryError.outOfBounds } let byteCursor = index / byteSize let bitindex = 7 - (index % byteSize) @@ -76,7 +71,7 @@ public struct Binary { /// Returns the `Int`-value of the given range. public mutating func getBits(range: Range) throws -> Int { guard (0...(bytesStore.count * byteSize)).contains(range.endIndex) else { - throw BinError.outOfBounds + throw BinaryError.outOfBounds } return try range.reversed().enumerated().reduce(0) { $0 + Int(try getBit(index: $1.element) << $1.offset) @@ -87,7 +82,7 @@ public struct Binary { public func getByte(index: Int) throws -> UInt8 { /// Check if `index` is within bounds of `bytes` guard (0..<(bytesStore.count)).contains(index) else { - throw BinError.outOfBounds + throw BinaryError.outOfBounds } return bytesStore[index] } @@ -95,7 +90,7 @@ public struct Binary { /// Returns an `[UInt8]` of the given `range`. public func getBytes(range: Range) throws -> [UInt8] { guard (0...(bytesStore.count)).contains(range.endIndex) else { - throw BinError.outOfBounds + throw BinaryError.outOfBounds } return Array(bytesStore[range]) } @@ -119,7 +114,7 @@ public struct Binary { /// and increments the reading cursor by n-bits. public mutating func readBits(quantitiy: Int) throws -> Int { guard (0...(bytesStore.count * byteSize)).contains(bitCursor + quantitiy) else { - throw BinError.outOfBounds + throw BinaryError.outOfBounds } let result = try (bitCursor..<(bitCursor + quantitiy)).reversed().enumerated().reduce(0) { $0 + Int(try getBit(index: $1.element) << $1.offset) @@ -148,7 +143,7 @@ public struct Binary { /// increments the reading cursor by n-bytes. public mutating func readString(quantitiyOfBytes quantitiy: Int, encoding: String.Encoding = .utf8) throws -> String { guard let result = String(bytes: try self.readBytes(quantitiy: quantitiy), encoding: encoding) else { - throw BinError.notString + throw BinaryError.notString } return result } diff --git a/Sources/BinaryKit/BinaryError.swift b/Sources/BinaryKit/BinaryError.swift new file mode 100644 index 0000000..e50c867 --- /dev/null +++ b/Sources/BinaryKit/BinaryError.swift @@ -0,0 +1,13 @@ +// +// File.swift +// +// +// Created by Devran on 27.09.19. +// + +import Foundation + +enum BinaryError: Error { + case outOfBounds + case notString +} From 4d5fbe88f078826d6513c1567c461ff961ff3462 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Devran=20=C3=9Cnal?= Date: Sat, 28 Sep 2019 11:56:10 +0200 Subject: [PATCH 13/13] Update README.md --- README.md | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/README.md b/README.md index 9ea206e..95584f9 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,6 @@ try binary.readBits(quantitiy: 4) ## Example -This shows how easy it is, to break down an [IPv4 header](https://en.wikipedia.org/wiki/IPv4#Header). - ```swift let binary = Binary(bytes: [0b1_1_0_1_1_1_0_0]) | | | | | | | | @@ -47,6 +45,7 @@ let binary = Binary(bytes: [0b1_1_0_1_1_1_0_0]) try binary.bit() // 1 ``` +This shows how easy it is, to break down an [IPv4 header](https://en.wikipedia.org/wiki/IPv4#Header). ```swift let binary = Binary(bytes: [0x1B, 0x44, …])