From b020fb294425df7853a1931498278ee362104ee8 Mon Sep 17 00:00:00 2001 From: Adam Rocska Date: Thu, 30 Apr 2020 13:27:23 +0200 Subject: [PATCH] Finally got a concept on how to program this in a non-convoluted way. - Extended UInt8 with a nice and juicy bitmask helper function - Foundation for a ControlByte type Signed-off-by: Adam Rocska --- Sources/MaxMindDBReader/ControlByte.swift | 17 ++++++++++ Sources/MaxMindDBReader/UInt8.swift | 9 +++++ .../ControlByteTest.swift | 33 ++++++++++++++++++ Tests/MaxMindDBReaderTests/UInt8Test.swift | 34 +++++++++++++++++++ 4 files changed, 93 insertions(+) create mode 100644 Sources/MaxMindDBReader/ControlByte.swift create mode 100644 Sources/MaxMindDBReader/UInt8.swift create mode 100644 Tests/MaxMindDBReaderTests/ControlByteTest.swift create mode 100644 Tests/MaxMindDBReaderTests/UInt8Test.swift diff --git a/Sources/MaxMindDBReader/ControlByte.swift b/Sources/MaxMindDBReader/ControlByte.swift new file mode 100644 index 0000000..0821cfb --- /dev/null +++ b/Sources/MaxMindDBReader/ControlByte.swift @@ -0,0 +1,17 @@ +import Foundation + +struct ControlByte { + + let type: DataType + + init?(firstByte: UInt8, secondByte: UInt8 = 0b0000_0000) { + let typeDefinitionOnFirstByte = firstByte &>> 5 + guard let type = typeDefinitionOnFirstByte != 0b0000_0000 + ? DataType(rawValue: typeDefinitionOnFirstByte) + : DataType(rawValue: secondByte + 7) + else { + return nil + } + self.type = type + } +} diff --git a/Sources/MaxMindDBReader/UInt8.swift b/Sources/MaxMindDBReader/UInt8.swift new file mode 100644 index 0000000..bc9ef48 --- /dev/null +++ b/Sources/MaxMindDBReader/UInt8.swift @@ -0,0 +1,9 @@ +import Foundation + +extension UInt8 { + + @inlinable func areBitsSet(bitMask: UInt8) -> Bool { + return (self & bitMask) > 0 + } + +} diff --git a/Tests/MaxMindDBReaderTests/ControlByteTest.swift b/Tests/MaxMindDBReaderTests/ControlByteTest.swift new file mode 100644 index 0000000..9d28297 --- /dev/null +++ b/Tests/MaxMindDBReaderTests/ControlByteTest.swift @@ -0,0 +1,33 @@ +import Foundation +import XCTest +@testable import MaxMindDBReader + +class ControlByteTest: XCTestCase { + func testInit() { + let dataTypes = (1...255).compactMap({ DataType(rawValue: $0) }) + + let nonExtendedTypes = dataTypes.filter({ $0.rawValue <= 7 }).map({ $0.rawValue }) + let extendedTypes = dataTypes.filter({ $0.rawValue > 7 }).map({ $0.rawValue }) + precondition(nonExtendedTypes.count > 0, "nonExtendedTypes can't be empty.") + precondition(extendedTypes.count > 0, "extendedTypes can't be empty.") + for nonExtendedType in nonExtendedTypes { + XCTAssertEqual( + DataType(rawValue: nonExtendedType), + ControlByte(firstByte: nonExtendedType &<< 5)?.type + ) + XCTAssertEqual( + DataType(rawValue: nonExtendedType), + ControlByte( + firstByte: nonExtendedType &<< 5, + secondByte: 0b1111_1111 + )?.type + ) + } + for extendedType in extendedTypes { + XCTAssertEqual( + DataType(rawValue: extendedType), + ControlByte(firstByte: 0b0000_0000, secondByte: extendedType - 7)?.type + ) + } + } +} diff --git a/Tests/MaxMindDBReaderTests/UInt8Test.swift b/Tests/MaxMindDBReaderTests/UInt8Test.swift new file mode 100644 index 0000000..d29e318 --- /dev/null +++ b/Tests/MaxMindDBReaderTests/UInt8Test.swift @@ -0,0 +1,34 @@ +import Foundation +import XCTest +@testable import MaxMindDBReader + +class UInt8Test: XCTestCase { + + func testAreBitsSet() { + XCTAssertTrue(UInt8(0b0010_0000).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertTrue(UInt8(0b0110_0000).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertTrue(UInt8(0b1110_0000).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertTrue(UInt8(0b1111_0000).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertTrue(UInt8(0b1111_1000).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertTrue(UInt8(0b1111_1100).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertTrue(UInt8(0b1111_1110).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertTrue(UInt8(0b1111_1111).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertFalse(UInt8(0b0000_0000).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertFalse(UInt8(0b0100_0000).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertFalse(UInt8(0b1100_0000).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertFalse(UInt8(0b1101_0000).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertFalse(UInt8(0b1101_1000).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertFalse(UInt8(0b1101_1100).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertFalse(UInt8(0b1101_1110).areBitsSet(bitMask: 0b0010_0000)) + XCTAssertFalse(UInt8(0b1101_1111).areBitsSet(bitMask: 0b0010_0000)) + + XCTAssertTrue(UInt8(0b1100_0000).areBitsSet(bitMask: 0b1100_0000)) + XCTAssertTrue(UInt8(0b1110_0000).areBitsSet(bitMask: 0b1100_0000)) + XCTAssertTrue(UInt8(0b1111_0000).areBitsSet(bitMask: 0b1100_0000)) + XCTAssertTrue(UInt8(0b1111_1000).areBitsSet(bitMask: 0b1100_0000)) + XCTAssertTrue(UInt8(0b1111_1100).areBitsSet(bitMask: 0b1100_0000)) + XCTAssertTrue(UInt8(0b1111_1110).areBitsSet(bitMask: 0b1100_0000)) + XCTAssertTrue(UInt8(0b1111_1111).areBitsSet(bitMask: 0b1100_0000)) + } + +}