pub const fn decode_pct_hex(c0: &char, c1: &char) -> Result<u8, ()> {
if let Ok(higher) = decode_hex(c0)
&& let Ok(lower) = decode_hex(c1)
{
Ok((higher << 4) | lower)
} else {
Err(())
}
}
pub const fn decode_hex(c: &char) -> Result<u8, ()> {
let byte = match c {
'0'..='9' => *c as u8 - b'0',
'a'..='f' => *c as u8 - b'a' + 10,
'A'..='F' => *c as u8 - b'A' + 10,
_ => return Err(()),
};
Ok(byte)
}
pub const fn decode_digit(c: &char) -> Result<u8, ()> {
let byte = match c {
'0'..='9' => *c as u8 - b'0',
_ => return Err(()),
};
Ok(byte)
}
pub const fn pct_encode_byte(byte: &u8) -> [char; 3] {
const HEX_CHARS: &[u8; 16] = b"0123456789ABCDEF";
[
'%',
HEX_CHARS[(*byte >> 4) as usize] as char,
HEX_CHARS[(*byte & 0x0F) as usize] as char,
]
}
#[inline(always)]
pub fn truncate_str(s: &str, n: usize) -> &str {
match s.char_indices().nth(n) {
None => s,
Some((idx, _)) => &s[0..idx],
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_truncate_str() {
assert_eq!(truncate_str("Hello, World!", 3), "Hel");
assert_eq!(truncate_str("Hello, World!", 13), "Hello, World!");
assert_eq!(truncate_str("Hello, World!", 20), "Hello, World!");
assert_eq!(truncate_str("你好,世界!", 1), "你");
assert_eq!(truncate_str("你好,世界!", 2), "你好");
assert_eq!(truncate_str("你好,世界!", 6), "你好,世界!");
assert_eq!(truncate_str("你好,世界!", 10), "你好,世界!");
}
}