diff --git a/Sources/Hex/Data+Hex.swift b/Sources/Hex/Data+Hex.swift index 7a1060c..d899ee1 100644 --- a/Sources/Hex/Data+Hex.swift +++ b/Sources/Hex/Data+Hex.swift @@ -11,7 +11,7 @@ extension Data { guard let bytes = Data.decode(hexData) else { return nil } - self = Data(bytes) + self = bytes } /// Creates data with the Hexadecimal (also known as Base-16) encoded string. @@ -25,21 +25,32 @@ extension Data { guard let bytes = hexString.withUTF8(Data.decode(_:)) else { return nil } - self = Data(bytes) + self = bytes } - private static func decode(_ input: some Sequence) -> [UInt8]? { - var bytes = [UInt8]() - var it = input.makeIterator() - while true { - switch Base16.decode(&it) { - case .emptyInput: - return bytes - case .error: - return nil - case .byteValue(let byte): - bytes.append(byte) + private static func decode(_ input: some Collection) -> Data? { + let capacity = Base16.estimateDecodedCount(length: input.count) + var bytes = Data(count: capacity) + let count = bytes.withUnsafeMutableBytes { raw in + raw.withMemoryRebound(to: UInt8.self) { buffer in + var i = 0 + var it = input.makeIterator() + while true { + switch Base16.decode(&it) { + case .emptyInput: + return i + case .error: + return -1 + case .byteValue(let byte): + buffer[i] = byte + i += 1 + } + } } } + guard count == capacity else { + return nil + } + return bytes } } diff --git a/Sources/Hex/Sequence+Hex.swift b/Sources/Hex/Sequence+Hex.swift index 9ee5f71..719fe01 100644 --- a/Sources/Hex/Sequence+Hex.swift +++ b/Sources/Hex/Sequence+Hex.swift @@ -6,7 +6,7 @@ extension Sequence { /// - Parameter options: Encoding options. Default value is `[]`. @inlinable public func hexEncodedData(options: Base16.EncodingOptions = []) -> Data { - Data(EncoderSequence(sequence: self, options: options)) + Data(Base16EncodingSequence(sequence: self, options: options)) } /// Returns the Hexadecimal (also known as Base-16) encoded string. @@ -14,12 +14,12 @@ extension Sequence { /// - Parameter options: Encoding options. Default value is `[]`. @inlinable public func hexEncodedString(options: Base16.EncodingOptions = []) -> String { - String(bytes: EncoderSequence(sequence: self, options: options), encoding: .utf8)! + String(bytes: Base16EncodingSequence(sequence: self, options: options), encoding: .utf8)! } } @usableFromInline -struct EncoderSequence>: Sequence { +struct Base16EncodingSequence>: Sequence { private let sequence: S private let options: Base16.EncodingOptions