builtin: implement a s.hex() method, allowing shortening s.bytes().hex() chains, and reducing the intermediate allocations; add tests for it (#22540)

This commit is contained in:
Delyan Angelov 2024-10-16 14:18:10 +03:00 committed by GitHub
parent a2e478be81
commit c5e8ad19df
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
11 changed files with 54 additions and 35 deletions

View file

@ -952,27 +952,12 @@ pub fn (a []string) str() string {
return res
}
// hex returns a string with the hexadecimal representation
// of the byte elements of the array.
// hex returns a string with the hexadecimal representation of the byte elements of the array `b`.
pub fn (b []u8) hex() string {
mut hex := unsafe { malloc_noscan(u64(b.len) * 2 + 1) }
mut dst_i := 0
for i in b {
n0 := i >> 4
unsafe {
hex[dst_i] = if n0 < 10 { n0 + `0` } else { n0 + u8(87) }
dst_i++
}
n1 := i & 0xF
unsafe {
hex[dst_i] = if n1 < 10 { n1 + `0` } else { n1 + u8(87) }
dst_i++
}
}
unsafe {
hex[dst_i] = 0
return tos(hex, dst_i)
if b.len == 0 {
return ''
}
return unsafe { data_to_hex_string(&u8(b.data), b.len) }
}
// copy copies the `src` byte array elements to the `dst` byte array.

View file

@ -2857,3 +2857,31 @@ pub fn (s string) wrap(config WrapConfig) string {
}
return sb.str()
}
// hex returns a string with the hexadecimal representation of the bytes of the string `s`
pub fn (s string) hex() string {
if s == '' {
return ''
}
return unsafe { data_to_hex_string(&u8(s.str), s.len) }
}
@[unsafe]
fn data_to_hex_string(data &u8, len int) string {
mut hex := unsafe { malloc_noscan(u64(len) * 2 + 1) }
mut dst := 0
for c in 0 .. len {
b := data[c]
n0 := b >> 4
n1 := b & 0xF
unsafe {
hex[dst] = if n0 < 10 { n0 + `0` } else { n0 + `W` }
hex[dst + 1] = if n1 < 10 { n1 + `0` } else { n1 + `W` }
}
dst += 2
}
unsafe {
hex[dst] = 0
return tos(hex, dst)
}
}

View file

@ -1577,3 +1577,12 @@ fn test_string_wrap() {
assert 'The V programming language'.wrap(width: 20, end: '|') == 'The V programming|language'
assert 'Hello, my name is Carl and I am a delivery'.wrap(width: 20) == 'Hello, my name is\nCarl and I am a\ndelivery'
}
fn test_hex() {
assert 'Hello World!'.hex() == '48656c6c6f20576f726c6421'
assert 'VLANG'.hex() == '564c414e47'
assert 'VLANG'.hex() == 'VLANG'.bytes().hex()
for c in u8(0) .. 255 {
assert c.ascii_str().hex() == [c].hex()
}
}

View file

@ -9,7 +9,7 @@ fn test_encode() {
'\x00\x00hello world': '11StV1DL6CwTryKyV'
} {
output := base58.encode(input)
println('> input: `${input}` | ${input.bytes().hex()} | => output: `${output}`')
println('> input: `${input}` | ${input.hex()} | => output: `${output}`')
assert output == expected
}
}
@ -36,7 +36,7 @@ fn test_decode() {
'3vQB7B6MrGQZaxCuFg4oh': hex.decode('68656c6c6f20776f726c64bc62d4b8')!.bytestr()
} {
input := base58.decode(output)!
println('> output: `${output}` | decoded input: `${input}` | bytes: ${input.bytes().hex()}')
assert input.bytes().hex() == expected.bytes().hex()
println('> output: `${output}` | decoded input: `${input}` | bytes: ${input.hex()}')
assert input.hex() == expected.hex()
}
}

View file

@ -509,8 +509,6 @@ fn test_write_lines() {
os.write_lines(wline2_file, lines)!
c1 := os.read_file(wline1_file)!
c2 := os.read_file(wline2_file)!
// dump(c1.bytes().hex())
// dump(c2.bytes().hex())
assert c1 == c2
assert c1.split_into_lines() == some_lines_content.split_into_lines()
}

View file

@ -872,7 +872,7 @@ fn test_execute() {
os.rm(print0script) or {}
}
result := os.execute('${os.quoted_path(@VEXE)} run ${os.quoted_path(print0script)}')
hexresult := result.output.bytes().hex()
hexresult := result.output.hex()
// println('exit_code: $result.exit_code')
// println('output: |$result.output|')
// println('output.len: $result.output.len')

View file

@ -419,8 +419,8 @@ fn diff_content(expected string, found string) {
println('expected bytes:\n${chunka(expected.bytes(), 25)}')
println(' found bytes:\n${chunka(found.bytes(), 25)}')
println('============')
println(' expected hex:\n${chunks(expected.bytes().hex(), 80)}')
println(' found hex:\n${chunks(found.bytes().hex(), 80)}')
println(' expected hex:\n${chunks(expected.hex(), 80)}')
println(' found hex:\n${chunks(found.hex(), 80)}')
}
println('============\n')
}

View file

@ -168,8 +168,8 @@ fn string_interpolation_with_negative_format_width_should_compile_and_run_withou
i := 3
input := '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
println('---------------------------------------------------------------------------------------------')
println('+60 ${i:10} | input.len: ${input.len:10} | ${input.bytes().hex():60} | $input')
println('-60 ${i:10} | input.len: ${input.len:10} | ${input.bytes().hex():-60} | $input')
println('+60 ${i:10} | input.len: ${input.len:10} | ${input.hex():60} | $input')
println('-60 ${i:10} | input.len: ${input.len:10} | ${input.hex():-60} | $input')
println('---------------------------------------------------------------------------------------------')
println(true)
}

View file

@ -9,6 +9,5 @@ fn test_cstring() {
fn test_cstring_with_zeros() {
rawbytes := &char(c'\x00username\x00password')
s := unsafe { rawbytes.vstring_with_len(18) }
h := s.bytes().hex()
assert h == '00757365726e616d650070617373776f7264'
assert s.hex() == '00757365726e616d650070617373776f7264'
}

View file

@ -165,8 +165,8 @@ fn test_string_interpolation_with_negative_format_width_should_compile_and_run_w
i := 3
input := '{"jsonrpc":"2.0","id":1,"method":"initialize","params":{}}'
eprintln('---------------------------------------------------------------------------------------------')
eprintln('+60 ${i:10} | input.len: ${input.len:10} | ${input.bytes().hex():60} | ${input}')
eprintln('-60 ${i:10} | input.len: ${input.len:10} | ${input.bytes().hex():-60} | ${input}')
eprintln('+60 ${i:10} | input.len: ${input.len:10} | ${input.hex():60} | ${input}')
eprintln('-60 ${i:10} | input.len: ${input.len:10} | ${input.hex():-60} | ${input}')
eprintln('---------------------------------------------------------------------------------------------')
assert true
}

View file

@ -1,8 +1,8 @@
const text = 'Hello world'
fn test_go_call_fn_return() {
hex_go := spawn text.bytes().hex()
hex := text.bytes().hex()
hex_go := spawn text.hex()
hex := text.hex()
assert hex == '48656c6c6f20776f726c64'
assert hex_go.wait() == hex