xmpp-parsers: Add a hexadecimal codec

That one accepts both uppercase and lowercase hexadecimal input, and
outputs in lowercase.

It requires no separator between bytes, unlike ColonSeparatedHex.
This commit is contained in:
Emmanuel Gil Peyrot 2024-01-05 17:36:43 +01:00
parent 54de8d9951
commit 3f90e84c5b

View file

@ -84,6 +84,27 @@ impl WhitespaceAwareBase64 {
} }
} }
/// Codec for bytes of lowercase hexadecimal.
pub struct Hex;
impl Hex {
pub fn decode(s: &str) -> Result<Vec<u8>, Error> {
let mut bytes = Vec::with_capacity(s.len() / 2);
for i in 0..s.len() / 2 {
bytes.push(u8::from_str_radix(&s[2 * i..2 * i + 2], 16)?);
}
Ok(bytes)
}
pub fn encode(b: &[u8]) -> Option<String> {
let mut bytes = String::with_capacity(b.len() * 2);
for byte in b {
bytes.extend(format!("{:02x}", byte).chars());
}
Some(bytes)
}
}
/// Codec for colon-separated bytes of uppercase hexadecimal. /// Codec for colon-separated bytes of uppercase hexadecimal.
pub struct ColonSeparatedHex; pub struct ColonSeparatedHex;
@ -121,3 +142,30 @@ impl JidCodec {
Some(jid.to_string()) Some(jid.to_string())
} }
} }
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn hex() {
let value = [0x01, 0xfe, 0xef];
// Test that we support both lowercase and uppercase as input.
let hex = Hex::decode("01feEF").unwrap();
assert_eq!(hex, &value);
// Test that we do output lowercase.
let hex = Hex::encode(&value).unwrap();
assert_eq!(hex, "01feef");
}
#[test]
fn bad_hex() {
// No colon supported.
Hex::decode("01:fe:EF").unwrap_err();
// No non-hex character allowed.
Hex::decode("01defg").unwrap_err();
}
}