// Copyright © 2020 Metabolist. All rights reserved. import Foundation public enum Base16EncodingError: Error { case invalidLength case invalidByteString(String) case invalidStringEncoding } public extension Data { enum Base16EncodingOptions { case uppercase } func base16EncodedString(options: [Base16EncodingOptions] = []) -> String { map { String(format: Self.format(options: options), $0) }.joined() } func base16EncodedData(options: [Base16EncodingOptions] = []) -> Data { Data(base16EncodedString(options: options).utf8) } init(base16Encoded string: String) throws { let stringLength = string.count guard stringLength % 2 == 0 else { throw Base16EncodingError.invalidLength } var data = [UInt8]() data.reserveCapacity(stringLength / 2) var i = string.startIndex while i != string.endIndex { let j = string.index(i, offsetBy: 2) let byteString = string[i.. String { options.contains(.uppercase) ? uppercaseBase16Format : lowercaseBase16Format } }