Initial project import
This commit is contained in:
commit
23f2d29e32
11957 files changed
+1754577
No files matched your search
@@ -0,0 +1,99 @@
|
||||
module hex
|
||||
|
||||
const hex_digits = '0123456789abcdef'
|
||||
const hex_digits_upper = '0123456789ABCDEF'
|
||||
|
||||
// EncodeParams configures optional output formatting for encode.
|
||||
//
|
||||
// If `uppercase` is set, `encode` emits `A-F` instead of `a-f`.
|
||||
// If `with_prefix` is non-empty, `encode` prepends that exact string.
|
||||
@[params]
|
||||
pub struct EncodeParams {
|
||||
pub mut:
|
||||
uppercase bool
|
||||
with_prefix string
|
||||
}
|
||||
|
||||
// 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, the first digit is
|
||||
// decoded as if an implicit `0` preceded it. An optional `0x` or `0X` prefix
|
||||
// is accepted.
|
||||
@[direct_array_access]
|
||||
pub fn decode(s string) ![]u8 {
|
||||
if s.len == 0 {
|
||||
return []u8{}
|
||||
}
|
||||
|
||||
mut offset := 0
|
||||
mut hex_bytes := if s.len >= 2 {
|
||||
if s[0] == `0` && (s[1] == `x` || s[1] == `X`) {
|
||||
offset = 2
|
||||
s[2..].bytes()
|
||||
} else {
|
||||
s.bytes()
|
||||
}
|
||||
} else {
|
||||
s.bytes()
|
||||
}
|
||||
|
||||
if hex_bytes.len == 0 {
|
||||
return []u8{}
|
||||
}
|
||||
|
||||
mut bytes := []u8{cap: (hex_bytes.len + 1) >> 1}
|
||||
mut start := 0
|
||||
if hex_bytes.len & 1 == 1 {
|
||||
bytes << char2nibble(hex_bytes[0], offset)!
|
||||
start = 1
|
||||
}
|
||||
|
||||
for i := start; i < hex_bytes.len; i += 2 {
|
||||
n1 := char2nibble(hex_bytes[i], offset + i)!
|
||||
n0 := char2nibble(hex_bytes[i + 1], offset + 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 whose length will be a multiple of 2.
|
||||
// If `EncodeParams.uppercase` is set, the output hex characters are emitted in
|
||||
// uppercase.
|
||||
// If `EncodeParams.with_prefix` is non-empty, the output string is prefixed
|
||||
// with the provided string.
|
||||
@[direct_array_access]
|
||||
pub fn encode(bytes []u8, params EncodeParams) string {
|
||||
if bytes.len == 0 {
|
||||
return ''
|
||||
}
|
||||
mut res := []u8{}
|
||||
if params.with_prefix != '' {
|
||||
res << params.with_prefix.bytes()
|
||||
}
|
||||
for _, b in bytes {
|
||||
res << nibble2char(b >> 4, params)
|
||||
res << nibble2char(b & 0xf, params)
|
||||
}
|
||||
return res.bytestr()
|
||||
}
|
||||
|
||||
// nibble2char converts a 4-bit hex value to its ASCII character
|
||||
@[inline]
|
||||
fn nibble2char(nibble u8, params EncodeParams) u8 {
|
||||
if params.uppercase {
|
||||
return hex_digits_upper[nibble]
|
||||
}
|
||||
return hex_digits[nibble]
|
||||
}
|
||||
|
||||
// char2nibble converts an ASCII hex character to its hex value
|
||||
@[inline]
|
||||
fn char2nibble(b u8, index int) !u8 {
|
||||
match b {
|
||||
`0`...`9` { return b - u8(`0`) }
|
||||
`A`...`F` { return b - u8(`A`) + 10 }
|
||||
`a`...`f` { return b - u8(`a`) + 10 }
|
||||
else { return error('invalid hex char ${b.ascii_str()} at index ${index}') }
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user