diff --git a/Makefile b/Makefile index 624a6cd..a52e991 100644 --- a/Makefile +++ b/Makefile @@ -1,9 +1,8 @@ -lint: - swiftlint autocorrect --format +SWIFT_PACKAGE_VERSION := $(shell swift package tools-version) -genLinuxTests: - swift test --generate-linuxmain - swiftlint autocorrect --format --path Tests/ +lint-fix: + mint run swiftlint --fix --quiet + mint run swiftformat --quiet --swiftversion ${SWIFT_PACKAGE_VERSION} . test: genLinuxTests swift test @@ -18,16 +17,9 @@ clean: cleanArtifacts: swift package clean -genXcode: - swift package generate-xcodeproj --enable-code-coverage --skip-extra-files - latest: swift package update resolve: swift package resolve -genXcodeOpen: genXcode - open *.xcodeproj - -precommit: lint genLinuxTests diff --git a/Mintfile b/Mintfile new file mode 100644 index 0000000..4b20408 --- /dev/null +++ b/Mintfile @@ -0,0 +1,2 @@ +realm/SwiftLint@0.51.0 +nicklockwood/SwiftFormat@0.51.7 diff --git a/Package.resolved b/Package.resolved index b1a5fbb..60105d2 100644 --- a/Package.resolved +++ b/Package.resolved @@ -6,8 +6,8 @@ "repositoryURL": "https://github.com/apple/swift-crypto.git", "state": { "branch": null, - "revision": "8f4bfa5bc1951440c15710e9e893721aa4b2765c", - "version": "1.1.3" + "revision": "33a20e650c33f6d72d822d558333f2085effa3dc", + "version": "2.5.0" } } ] diff --git a/Package.swift b/Package.swift index 5401daf..74ce3d8 100644 --- a/Package.swift +++ b/Package.swift @@ -4,9 +4,9 @@ import PackageDescription let swiftSettings: [SwiftSetting]? #if canImport(Foundation) -swiftSettings = nil + swiftSettings = nil #else -swiftSettings = [.define("USE_FRB_UUID")] + swiftSettings = [.define("USE_FRB_UUID")] #endif let package = Package( @@ -20,17 +20,20 @@ let package = Package( products: [ .library( name: "FirebladeUUID", - targets: ["FirebladeUUID"]) + targets: ["FirebladeUUID"] + ), ], dependencies: [.package(url: "https://github.com/apple/swift-crypto.git", from: "2.5.0")], targets: [ .target( name: "FirebladeUUID", dependencies: [.product(name: "Crypto", package: "swift-crypto")], - swiftSettings: swiftSettings), + swiftSettings: swiftSettings + ), .testTarget( name: "FirebladeUUIDTests", - dependencies: ["FirebladeUUID"]) + dependencies: ["FirebladeUUID"] + ), ], swiftLanguageVersions: [.v5] ) diff --git a/Sources/FirebladeUUID/Shims.swift b/Sources/FirebladeUUID/Shims.swift index fcd2327..90117d2 100644 --- a/Sources/FirebladeUUID/Shims.swift +++ b/Sources/FirebladeUUID/Shims.swift @@ -6,11 +6,11 @@ // #if USE_FRB_UUID -public typealias UUID = FRB_UUID -public typealias UUID_t = (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) + public typealias UUID = FRB_UUID + public typealias UUID_t = (UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8, UInt8) #else -import struct Foundation.UUID -import typealias Foundation.uuid_t -public typealias UUID = Foundation.UUID -public typealias UUID_t = uuid_t + import struct Foundation.UUID + import typealias Foundation.uuid_t + public typealias UUID = Foundation.UUID + public typealias UUID_t = uuid_t #endif diff --git a/Sources/FirebladeUUID/UUID+Extensions.swift b/Sources/FirebladeUUID/UUID+Extensions.swift index 26b47b2..1ca2da9 100644 --- a/Sources/FirebladeUUID/UUID+Extensions.swift +++ b/Sources/FirebladeUUID/UUID+Extensions.swift @@ -22,8 +22,8 @@ extension UUID { } } precondition(written == UUID.count) - uuidBytes.6 = (uuidBytes.6 & 0x0f) | 0x40 // version https://tools.ietf.org/html/rfc4122#section-4.1.3 - uuidBytes.8 = (uuidBytes.8 & 0x3f) | 0x80 // variant https://tools.ietf.org/html/rfc4122#section-4.1.1 + uuidBytes.6 = (uuidBytes.6 & 0x0F) | 0x40 // version https://tools.ietf.org/html/rfc4122#section-4.1.3 + uuidBytes.8 = (uuidBytes.8 & 0x3F) | 0x80 // variant https://tools.ietf.org/html/rfc4122#section-4.1.1 self.init(uuid: uuidBytes) } } diff --git a/Sources/FirebladeUUID/UUID+Name.swift b/Sources/FirebladeUUID/UUID+Name.swift index c3dbd7e..a9315b4 100644 --- a/Sources/FirebladeUUID/UUID+Name.swift +++ b/Sources/FirebladeUUID/UUID+Name.swift @@ -7,8 +7,8 @@ import Crypto -extension UUID { - public init(name: String, namespace: UUID) { +public extension UUID { + init(name: String, namespace: UUID) { var hasher = Crypto.Insecure.SHA1() hasher.update(uuidBytes: namespace.uuid) hasher.update(collection: name.utf8) @@ -16,31 +16,31 @@ extension UUID { } } -extension UUID { +public extension UUID { /// UUID Namespace /// /// - public enum Namespace { } + enum Namespace {} } -extension UUID.Namespace { +public extension UUID.Namespace { /// Name string is a fully-qualified domain name /// /// `6ba7b810-9dad-11d1-80b4-00c04fd430c8` - public static let DNS = UUID(uuid: UUID_t(0x6b, 0xa7, 0xb8, 0x10, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8)) + static let DNS = UUID(uuid: UUID_t(0x6B, 0xA7, 0xB8, 0x10, 0x9D, 0xAD, 0x11, 0xD1, 0x80, 0xB4, 0x00, 0xC0, 0x4F, 0xD4, 0x30, 0xC8)) /// Name string is a URL /// /// `6ba7b811-9dad-11d1-80b4-00c04fd430c8` - public static let URL = UUID(uuid: UUID_t(0x6b, 0xa7, 0xb8, 0x11, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8)) + static let URL = UUID(uuid: UUID_t(0x6B, 0xA7, 0xB8, 0x11, 0x9D, 0xAD, 0x11, 0xD1, 0x80, 0xB4, 0x00, 0xC0, 0x4F, 0xD4, 0x30, 0xC8)) /// Name string is an ISO OID /// /// `6ba7b812-9dad-11d1-80b4-00c04fd430c8` - public static let OID = UUID(uuid: UUID_t(0x6b, 0xa7, 0xb8, 0x12, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8)) + static let OID = UUID(uuid: UUID_t(0x6B, 0xA7, 0xB8, 0x12, 0x9D, 0xAD, 0x11, 0xD1, 0x80, 0xB4, 0x00, 0xC0, 0x4F, 0xD4, 0x30, 0xC8)) /// Name string is an X.500 DN (in DER or a text output format) /// /// `6ba7b814-9dad-11d1-80b4-00c04fd430c8` - public static let X500 = UUID(uuid: UUID_t(0x6b, 0xa7, 0xb8, 0x14, 0x9d, 0xad, 0x11, 0xd1, 0x80, 0xb4, 0x00, 0xc0, 0x4f, 0xd4, 0x30, 0xc8)) + static let X500 = UUID(uuid: UUID_t(0x6B, 0xA7, 0xB8, 0x14, 0x9D, 0xAD, 0x11, 0xD1, 0x80, 0xB4, 0x00, 0xC0, 0x4F, 0xD4, 0x30, 0xC8)) } diff --git a/Sources/FirebladeUUID/UUID.swift b/Sources/FirebladeUUID/UUID.swift index 44bdde1..165114b 100644 --- a/Sources/FirebladeUUID/UUID.swift +++ b/Sources/FirebladeUUID/UUID.swift @@ -6,161 +6,161 @@ // #if USE_FRB_UUID -/// A RFC4122 compliant Universally Unique IDentifier (UUID). -/// -/// -public struct FRB_UUID { - @usableFromInline let bytes: ContiguousArray - - public init(_ bytes: ContiguousArray) { - precondition(bytes.count == FRB_UUID.count, "A UUID must have a count of exactly \(FRB_UUID.count).") - self.bytes = bytes - } - - public init(uuid: UUID_t) { - let bytes = withUnsafePointer(to: uuid) { ptr -> ContiguousArray in - let start = UnsafeRawPointer(ptr).assumingMemoryBound(to: UInt8.self) - let count = MemoryLayout.stride / MemoryLayout.stride - let buffer = UnsafeBufferPointer(start: start, count: count) - return ContiguousArray(buffer) + /// A RFC4122 compliant Universally Unique IDentifier (UUID). + /// + /// + public struct FRB_UUID { + @usableFromInline let bytes: ContiguousArray + + public init(_ bytes: ContiguousArray) { + precondition(bytes.count == FRB_UUID.count, "A UUID must have a count of exactly \(FRB_UUID.count).") + self.bytes = bytes } - self.init(bytes) - } - public init() { - self.init(FRB_UUID.generateUUID()) - } - - public init?(uuidString: String) { - // "An UUID string must have a count of exactly 36." - guard uuidString.count == 2 * FRB_UUID.count + 4 else { - return nil + public init(uuid: UUID_t) { + let bytes = withUnsafePointer(to: uuid) { ptr -> ContiguousArray in + let start = UnsafeRawPointer(ptr).assumingMemoryBound(to: UInt8.self) + let count = MemoryLayout.stride / MemoryLayout.stride + let buffer = UnsafeBufferPointer(start: start, count: count) + return ContiguousArray(buffer) + } + self.init(bytes) } - var uuid: ContiguousArray = ContiguousArray(repeating: 0, count: FRB_UUID.count) - let contiguousString: String = uuidString.split(separator: "-").joined() - // An UUID string must have exactly 4 separators - guard contiguousString.count == 2 * FRB_UUID.count else { - return nil + public init() { + self.init(FRB_UUID.generateUUID()) } - var endIdx: String.Index = contiguousString.startIndex - for index in 0.. ContiguousArray { - #if swift(>=5.1) - var uuid: ContiguousArray = ContiguousArray(unsafeUninitializedCapacity: FRB_UUID.count) { uuidPtr, written in - for offset in 0..(repeating: 0, count: FRB_UUID.count) + let contiguousString: String = uuidString.split(separator: "-").joined() + // An UUID string must have exactly 4 separators + guard contiguousString.count == 2 * FRB_UUID.count else { + return nil } - written = FRB_UUID.count - } - #else - var uuid: ContiguousArray = ContiguousArray(repeating: 0, count: FRB_UUID.count) - for offset in 0.. ContiguousArray { + #if swift(>=5.1) + var uuid = ContiguousArray(unsafeUninitializedCapacity: FRB_UUID.count) { uuidPtr, written in + for offset in 0 ..< FRB_UUID.count { + uuidPtr[offset] = UInt8.random(in: UInt8.min ... UInt8.max) + } + written = FRB_UUID.count + } + #else + var uuid = ContiguousArray(repeating: 0, count: FRB_UUID.count) + for offset in 0 ..< FRB_UUID.count { + uuid[offset] = UInt8.random(in: UInt8.min ... UInt8.max) + } + + #endif + makeRFC4122compliant(uuid: &uuid) + return uuid + } - private static func makeRFC4122compliant(uuid: inout ContiguousArray) { - uuid[6] = (uuid[6] & 0x0f) | 0x40 // version https://tools.ietf.org/html/rfc4122#section-4.1.3 - uuid[8] = (uuid[8] & 0x3f) | 0x80 // variant https://tools.ietf.org/html/rfc4122#section-4.1.1 - } + private static func makeRFC4122compliant(uuid: inout ContiguousArray) { + uuid[6] = (uuid[6] & 0x0F) | 0x40 // version https://tools.ietf.org/html/rfc4122#section-4.1.3 + uuid[8] = (uuid[8] & 0x3F) | 0x80 // variant https://tools.ietf.org/html/rfc4122#section-4.1.1 + } - @inlinable public var uuidString: String { - var out = String() - out.reserveCapacity(FRB_UUID.count) - let separatorLayout: [Int] = [0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0] - let separator: String = "-" - var idx: Int = 0 - for byte in bytes { - let char = String(byte, radix: FRB_UUID.count, uppercase: true) - switch char.count { - case 2: - out.append(char) - - default: - out.append("0" + char) + @inlinable public var uuidString: String { + var out = String() + out.reserveCapacity(FRB_UUID.count) + let separatorLayout: [Int] = [0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0] + let separator = "-" + var idx = 0 + for byte in bytes { + let char = String(byte, radix: FRB_UUID.count, uppercase: true) + switch char.count { + case 2: + out.append(char) + + default: + out.append("0" + char) + } + if separatorLayout[idx] == 1 { + out.append(separator) + } + idx += 1 } - if separatorLayout[idx] == 1 { - out.append(separator) - } - idx += 1 + + precondition(idx == FRB_UUID.count) + precondition(out.count == 36) + return out } - precondition(idx == FRB_UUID.count) - precondition(out.count == 36) - return out - } + /// One-at-a-Time hash + /// http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx + @inlinable var oatHash: Int { + var hash = 0 - /// One-at-a-Time hash - /// http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx - @inlinable var oatHash: Int { - var hash: Int = 0 + for index: Int in 0 ..< FRB_UUID.count { + hash = hash &+ numericCast(bytes[index]) + hash = hash &+ (hash << 10) + hash ^= (hash >> 6) + } - for index: Int in 0..> 6) + hash = hash &+ (hash << 3) + hash ^= (hash << 11) + hash = hash &+ (hash << 15) + return hash } - hash = hash &+ (hash << 3) - hash ^= (hash << 11) - hash = hash &+ (hash << 15) - return hash + public var uuid: UUID_t { + UUID_t(bytes[0], + bytes[1], + bytes[2], + bytes[3], + bytes[4], + bytes[5], + bytes[6], + bytes[7], + bytes[8], + bytes[9], + bytes[10], + bytes[11], + bytes[12], + bytes[13], + bytes[14], + bytes[15]) + } } - public var uuid: UUID_t { - UUID_t(bytes[0], - bytes[1], - bytes[2], - bytes[3], - bytes[4], - bytes[5], - bytes[6], - bytes[7], - bytes[8], - bytes[9], - bytes[10], - bytes[11], - bytes[12], - bytes[13], - bytes[14], - bytes[15]) + extension FRB_UUID: Equatable { + public static func == (lhs: FRB_UUID, rhs: FRB_UUID) -> Bool { + lhs.bytes == rhs.bytes + } } -} -extension FRB_UUID: Equatable { - public static func == (lhs: FRB_UUID, rhs: FRB_UUID) -> Bool { - lhs.bytes == rhs.bytes + extension FRB_UUID: Hashable { + public func hash(into hasher: inout Hasher) { + hasher.combine(oatHash) + } } -} -extension FRB_UUID: Hashable { - public func hash(into hasher: inout Hasher) { - hasher.combine(oatHash) + extension FRB_UUID: CustomStringConvertible { + public var description: String { uuidString } } -} - -extension FRB_UUID: CustomStringConvertible { - public var description: String { uuidString } -} -extension FRB_UUID: CustomDebugStringConvertible { - public var debugDescription: String { uuidString } -} + extension FRB_UUID: CustomDebugStringConvertible { + public var debugDescription: String { uuidString } + } #endif diff --git a/Tests/FirebladeUUIDTests/FirebladeUUIDTests.swift b/Tests/FirebladeUUIDTests/FirebladeUUIDTests.swift index d7003dd..0d9148d 100644 --- a/Tests/FirebladeUUIDTests/FirebladeUUIDTests.swift +++ b/Tests/FirebladeUUIDTests/FirebladeUUIDTests.swift @@ -1,9 +1,9 @@ -import class XCTest.XCTestCase -import func XCTest.XCTAssertNotNil import func XCTest.XCTAssertEqual -import func XCTest.XCTAssertTrue import func XCTest.XCTAssertFalse import func XCTest.XCTAssertNil +import func XCTest.XCTAssertNotNil +import func XCTest.XCTAssertTrue +import class XCTest.XCTestCase import FirebladeUUID @@ -15,7 +15,7 @@ internal class FirebladeUUIDTests: XCTestCase { func testUniqueness() { var set = Set() - (0..<100_000).forEach { _ in + (0 ..< 100_000).forEach { _ in let (inserted, _) = set.insert(UUID()) XCTAssertTrue(inserted) } diff --git a/Tests/FirebladeUUIDTests/XCTestManifests.swift b/Tests/FirebladeUUIDTests/XCTestManifests.swift index 5c17547..ce0e2cb 100644 --- a/Tests/FirebladeUUIDTests/XCTestManifests.swift +++ b/Tests/FirebladeUUIDTests/XCTestManifests.swift @@ -1,34 +1,34 @@ #if !canImport(ObjectiveC) -import XCTest + import XCTest -extension FirebladeUUIDTests { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__FirebladeUUIDTests = [ - ("testInit", testInit), - ("testString", testString), - ("testUniqueness", testUniqueness), - ] -} + extension FirebladeUUIDTests { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__FirebladeUUIDTests = [ + ("testInit", testInit), + ("testString", testString), + ("testUniqueness", testUniqueness), + ] + } -extension NameBasedUUIDTests { - // DO NOT MODIFY: This is autogenerated, use: - // `swift test --generate-linuxmain` - // to regenerate. - static let __allTests__NameBasedUUIDTests = [ - ("testDifferentNamesSameSpaceNotEqual", testDifferentNamesSameSpaceNotEqual), - ("testDifferentTimesSameNameEqual", testDifferentTimesSameNameEqual), - ("testNamespaceDefinitions", testNamespaceDefinitions), - ("testSameNameSameSpacesEqual", testSameNameSameSpacesEqual), - ("testSameNamesDifferentSpacesNotEqual", testSameNamesDifferentSpacesNotEqual), - ] -} + extension NameBasedUUIDTests { + // DO NOT MODIFY: This is autogenerated, use: + // `swift test --generate-linuxmain` + // to regenerate. + static let __allTests__NameBasedUUIDTests = [ + ("testDifferentNamesSameSpaceNotEqual", testDifferentNamesSameSpaceNotEqual), + ("testDifferentTimesSameNameEqual", testDifferentTimesSameNameEqual), + ("testNamespaceDefinitions", testNamespaceDefinitions), + ("testSameNameSameSpacesEqual", testSameNameSameSpacesEqual), + ("testSameNamesDifferentSpacesNotEqual", testSameNamesDifferentSpacesNotEqual), + ] + } -public func __allTests() -> [XCTestCaseEntry] { - return [ - testCase(FirebladeUUIDTests.__allTests__FirebladeUUIDTests), - testCase(NameBasedUUIDTests.__allTests__NameBasedUUIDTests), - ] -} + public func __allTests() -> [XCTestCaseEntry] { + [ + testCase(FirebladeUUIDTests.__allTests__FirebladeUUIDTests), + testCase(NameBasedUUIDTests.__allTests__NameBasedUUIDTests), + ] + } #endif