Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mnemonic data #791

Merged
merged 12 commits into from
Nov 7, 2023
Original file line number Diff line number Diff line change
Expand Up @@ -17,16 +17,17 @@ extension BigInt: LiteralInitiableFromString { }
extension BigUInt: LiteralInitiableFromString { }

extension Data: LiteralInitiableFromString {
/// Converts hexadecimal string representation of some bytes into actual bytes.
/// Notes:
/// - empty string will return `nil`;
/// - empty hex string, meaning it's equal to `"0x"`, will return empty `Data` object.
/// - Parameter hex: bytes represented as string.
/// - Returns: optional raw bytes.
public static func fromHex(_ hex: String) -> Data? {
let string = hex.lowercased().stripHexPrefix()
let array = [UInt8](hex: string)
if array.count == 0 {
if hex == "0x" || hex == "" {
return Data()
} else {
return nil
}
}
return Data(array)
let hex = hex.lowercased().trim()
guard !hex.isEmpty else { return nil }
guard hex != "0x" else { return Data() }
let bytes = [UInt8](hex: hex.stripHexPrefix())
return bytes.isEmpty ? nil : Data(bytes)
}
}
39 changes: 21 additions & 18 deletions Sources/Web3Core/Utility/Data+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,8 @@

import Foundation

extension Data {
public extension Data {

init<T>(fromArray values: [T]) {
let values = values
let ptrUB = values.withUnsafeBufferPointer { (ptr: UnsafeBufferPointer) in return ptr }
Expand Down Expand Up @@ -33,32 +34,34 @@ extension Data {
return difference == UInt8(0x00)
}

public static func zero(_ data: inout Data) {
static func zero(_ data: inout Data) {
let count = data.count
data.withUnsafeMutableBytes { (body: UnsafeMutableRawBufferPointer) in
body.baseAddress?.assumingMemoryBound(to: UInt8.self).initialize(repeating: 0, count: count)
}
}

public static func randomBytes(length: Int) -> Data? {
for _ in 0...1024 {
pharms-eth marked this conversation as resolved.
Show resolved Hide resolved
var data = Data(repeating: 0, count: length)
let result = data.withUnsafeMutableBytes { (body: UnsafeMutableRawBufferPointer) -> Int32? in
if let bodyAddress = body.baseAddress, body.count > 0 {
let pointer = bodyAddress.assumingMemoryBound(to: UInt8.self)
return SecRandomCopyBytes(kSecRandomDefault, length, pointer)
} else {
return nil
}
}
if let notNilResult = result, notNilResult == errSecSuccess {
return data
}
/**
Generates an array of random bytes of the specified length.
This function uses `SecRandomCopyBytes` to generate random bytes returning it as a `Data` object.
If an error occurs during random bytes generation, the function returns `nil`.
Error occurs only if `SecRandomCopyBytes` returns status that is not `errSecSuccess`.
See [all status codes](https://developer.apple.com/documentation/security/1542001-security_framework_result_codes) for possible error reasons.
Note: in v4 of web3swift this function will be deprecated and a new implementation will be provided that will throw occurred error.
- Parameter length: The number of random bytes to generate.

JeneaVranceanu marked this conversation as resolved.
Show resolved Hide resolved
- Returns: optional `Data` object containing the generated random bytes, or `nil` if an error occurred during generation.
*/
static func randomBytes(length: Int) -> Data? {
var entropyBytes = [UInt8](repeating: 0, count: length)
let status = SecRandomCopyBytes(kSecRandomDefault, entropyBytes.count, &entropyBytes)
guard status == errSecSuccess else {
return nil
}
return nil
return Data(entropyBytes)
}

public func bitsInRange(_ startingBit: Int, _ length: Int) -> UInt64? { // return max of 8 bytes for simplicity, non-public
func bitsInRange(_ startingBit: Int, _ length: Int) -> UInt64? { // return max of 8 bytes for simplicity, non-public
if startingBit + length / 8 > self.count, length > 64, startingBit > 0, length >= 1 { return nil }
let bytes = self[(startingBit/8) ..< (startingBit+length+7)/8]
let padding = Data(repeating: 0, count: 8 - bytes.count)
Expand Down
20 changes: 20 additions & 0 deletions Sources/Web3Core/Utility/String+Extension.swift
Original file line number Diff line number Diff line change
Expand Up @@ -135,6 +135,26 @@ extension String {
func trim() -> String {
trimmingCharacters(in: .whitespacesAndNewlines)
}

/// Splits a string into groups of `every` n characters, grouping from left-to-right by default. If `backwards` is true, right-to-left.
public func split(every: Int, backwards: Bool = false) -> [String] {
var result = [String]()

for i in stride(from: 0, to: self.count, by: every) {
switch backwards {
case true:
let endIndex = self.index(self.endIndex, offsetBy: -i)
let startIndex = self.index(endIndex, offsetBy: -every, limitedBy: self.startIndex) ?? self.startIndex
result.insert(String(self[startIndex..<endIndex]), at: 0)
case false:
let startIndex = self.index(self.startIndex, offsetBy: i)
let endIndex = self.index(startIndex, offsetBy: every, limitedBy: self.endIndex) ?? self.endIndex
result.append(String(self[startIndex..<endIndex]))
}
}

return result
}
pharms-eth marked this conversation as resolved.
Show resolved Hide resolved
}

extension Character {
Expand Down
11 changes: 11 additions & 0 deletions Tests/web3swiftTests/localTests/UncategorizedTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,17 @@ class UncategorizedTests: XCTestCase {
XCTAssert(biguint == BigUInt("126978086000000000"))
}

func testStringSplit() {
XCTAssertEqual("abcdefgh".split(every: 3), ["abc", "def", "gh"])
XCTAssertEqual("abcdefgh".split(every: 3, backwards: true), ["ab", "cde", "fgh"])

XCTAssertEqual("abcdefgh".split(every: 10), ["abcdefgh"])
XCTAssertEqual("".split(every: 3), [])

XCTAssertEqual("abcdefgh".split(every: 1), ["a", "b", "c", "d", "e", "f", "g", "h"])
XCTAssertEqual("abcdefgh".split(every: 1, backwards: true), ["a", "b", "c", "d", "e", "f", "g", "h"]) // should be the same as from the front
}

func testBloom() throws {
let positive = [
"testtest",
Expand Down