The referenced PHP function returns a string with 3 decimal digits for
each UTF-8 code unit in the source string. In Swift that would be
func toNumbers(_ s: String) -> String {
return s.utf8.map { String(format: "%03d", $0) }.joined()
}
The reverse conversion is a bit more complicated because Swift has no
built-in function which corresponds to the PHP str_split()
.
We have to iterate over the indices in steps of 3, and convert
each slice to a byte:
func backToString(_ n: String) -> String? {
var utf8 = Data()
var from = n.startIndex
while from < n.endIndex {
guard let to = n.index(from, offsetBy: 3, limitedBy: n.endIndex) else { return nil }
guard let u = UInt8(n[from..<to]) else { return nil }
utf8.append(u)
from = to
}
return String(data: utf8, encoding: .utf8)
}
The function returns an optional because the conversion can fail.
Example usage:
let s = "Wörks wíth all ストリングズ"
let n = toNumbers(s)
print(n) // 087195182114107115032119195173116104032097108108032227130185227131136227131170227131179227130176227130186
if let s2 = backToString(n) {
print(s2) // Wörks wíth all ストリングズ
}
And just for fun: a more compact version of the second function:
func backToString(_ n: String) -> String? {
return String(bytes: sequence(state: n.startIndex, next: { (from: inout String.Index) -> UInt8? in
guard let to = n.index(from, offsetBy: 3, limitedBy: n.endIndex) else { return nil }
defer { from = to }
return UInt8(n[from..<to])
}), encoding: .utf8)
}