hex/binary string conversion in Swift

Data from Swift 3 has no “built-in” method to print its contents as
a hex string, or to create a Data value from a hex string.

“Data to hex string” methods can be found e.g. at How to convert Data to hex string in swift or How can I print the content of a variable of type Data using Swift? or converting String to Data in swift 3.0. Here is an implementation from the first link:

extension Data {
    func hexEncodedString() -> String {
        return map { String(format: "%02hhx", $0) }.joined()
    }
}

Here is a possible implementation of the reverse “hex string to Data”
conversion (taken from Hex String to Bytes (NSData) on Code Review, translated to Swift 3 and improved)
as a failable inititializer:

extension Data {

    init?(fromHexEncodedString string: String) {

        // Convert 0 ... 9, a ... f, A ...F to their decimal value,
        // return nil for all other input characters
        func decodeNibble(u: UInt8) -> UInt8? {
            switch(u) {
            case 0x30 ... 0x39:
                return u - 0x30
            case 0x41 ... 0x46:
                return u - 0x41 + 10
            case 0x61 ... 0x66:
                return u - 0x61 + 10
            default:
                return nil
            }
        }

        self.init(capacity: string.utf8.count/2)
        
        var iter = string.utf8.makeIterator()
        while let c1 = iter.next() {
            guard
                let val1 = decodeNibble(u: c1),
                let c2 = iter.next(),
                let val2 = decodeNibble(u: c2)
            else { return nil }
            self.append(val1 << 4 + val2)
        }
    }
}

Example:

// Hex string to Data:
if let data = Data(fromHexEncodedString: "0002468A13579BFF") {
    let idata = Data(data.map { 255 - $0 })
    
    // Data to hex string:
    print(idata.hexEncodedString()) // fffdb975eca86400
} else {
    print("invalid hex string")
}

Leave a Comment