aboutsummaryrefslogtreecommitdiff
path: root/v_windows/v/vlib/encoding/hex/hex.v
blob: 99387f15e7af9e5f614d28535398b5c49a5956e9 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
module hex

import strings

// decode converts a hex string into an array of bytes. The expected
// input format is 2 ASCII characters for each output byte. If the provided
// string length is not a multiple of 2, an implicit `0` is prepended to it.
pub fn decode(s string) ?[]byte {
	mut hex_str := s
	if hex_str.len >= 2 {
		if s[0] == `0` && (s[1] == `x` || s[1] == `X`) {
			hex_str = s[2..]
		}
	}
	if hex_str.len == 0 {
		return []byte{}
	} else if hex_str.len == 1 {
		return [char2nibble(hex_str[0]) ?]
	} else if hex_str.len == 2 {
		n1 := char2nibble(hex_str[0]) ?
		n0 := char2nibble(hex_str[1]) ?
		return [(n1 << 4) | n0]
	}
	// calculate the first byte depending on if hex_str.len is odd
	mut val := char2nibble(hex_str[0]) ?
	if hex_str.len & 1 == 0 {
		val = (val << 4) | char2nibble(hex_str[1]) ?
	}
	// set cap to hex_str.len/2 rounded up
	mut bytes := []byte{len: 1, cap: (hex_str.len + 1) >> 1, init: val}
	// iterate over every 2 bytes
	// the start index depends on if hex_str.len is odd
	for i := 2 - (hex_str.len & 1); i < hex_str.len; i += 2 {
		n1 := char2nibble(hex_str[i]) ?
		n0 := char2nibble(hex_str[i + 1]) ?
		bytes << (n1 << 4) | n0
	}
	return bytes
}

// encode converts an array of bytes into a string of ASCII hex bytes. The
// output will always be a string with length a multiple of 2.
[manualfree]
pub fn encode(bytes []byte) string {
	mut sb := strings.new_builder(bytes.len << 1)
	for b in bytes {
		sb.write_string(b.hex())
	}
	res := sb.str()
	unsafe { sb.free() }
	return res
}

// char2nibble converts an ASCII hex character to it's hex value
fn char2nibble(b byte) ?byte {
	match b {
		`0`...`9` { return b - byte(`0`) }
		`A`...`F` { return b - byte(`A`) + 10 }
		`a`...`f` { return b - byte(`a`) + 10 }
		else { return error('invalid hex char $b.ascii_str()') }
	}
}