diff --git a/Sources/BasedUtils/extensions/Data.swift b/Sources/BasedUtils/extensions/Data.swift index 7317c9d..e293118 100644 --- a/Sources/BasedUtils/extensions/Data.swift +++ b/Sources/BasedUtils/extensions/Data.swift @@ -9,6 +9,32 @@ import Foundation public extension Data { + /// Returns Data from given hex string. + /// - an empty string will return `nil`; + /// - an empty hex string is equal to `"0x"` and will return empty `Data` object. + /// - Parameter hex: bytes represented as string. + /// - Returns: optional raw bytes. + static func fromHex(_ hex: String) -> Data? { + let hex = hex.lowercased().trimmingCharacters(in: .whitespacesAndNewlines) + guard !hex.isEmpty else { return nil } + guard hex != "0x" else { return Data() } + let rawHex = hex.removeHexPrefix() + guard rawHex.count % 2 == 0 else { return nil } + var data = Data(capacity: rawHex.count / 2) + var index = rawHex.startIndex + while index < rawHex.endIndex { + let nextIndex = rawHex.index(index, offsetBy: 2) + let byteString = rawHex[index.. String { var base64String = self.base64EncodedString() // Replace standard Base64 characters to make it URL-safe @@ -20,4 +46,3 @@ public extension Data { } } - diff --git a/Tests/BasedUtilsTests/DataExtensionsTests.swift b/Tests/BasedUtilsTests/DataExtensionsTests.swift index 88c86f9..7e76f29 100644 --- a/Tests/BasedUtilsTests/DataExtensionsTests.swift +++ b/Tests/BasedUtilsTests/DataExtensionsTests.swift @@ -23,4 +23,11 @@ final class DataExtensionsTests: XCTestCase { XCTAssertEqual(emptyString.base64UrlEncode(), "") } + func testFromHex() throws { + XCTAssertEqual(Data.fromHex("0x"), Data()) + XCTAssertEqual(Data.fromHex("0x61"), Data([97])) + XCTAssertEqual(Data.fromHex("0x48656c6c6f20576f726c6421"), Data([72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100, 33])) + XCTAssertEqual(Data.fromHex("0x420fggf11a"), nil) + } + }