iroh_http_core/
encoding.rs1use crate::CoreError;
7
8pub fn base32_encode(bytes: &[u8]) -> String {
10 base32::encode(base32::Alphabet::Rfc4648Lower { padding: false }, bytes)
11}
12
13pub(crate) fn base32_decode(s: &str) -> Result<Vec<u8>, String> {
15 base32::decode(base32::Alphabet::Rfc4648Lower { padding: false }, s)
16 .ok_or_else(|| format!("invalid base32 string: {s}"))
17}
18
19pub(crate) fn parse_node_id(s: &str) -> Result<iroh::PublicKey, CoreError> {
21 let bytes = base32_decode(s).map_err(CoreError::invalid_input)?;
22 let arr: [u8; 32] = bytes
23 .try_into()
24 .map_err(|_| CoreError::invalid_input("node-id must be 32 bytes"))?;
25 iroh::PublicKey::from_bytes(&arr).map_err(|e| CoreError::invalid_input(e.to_string()))
26}
27
28#[cfg(test)]
29mod tests {
30 use super::*;
31
32 #[test]
33 fn base32_round_trip() {
34 let original: Vec<u8> = (0..32).collect();
35 let encoded = base32_encode(&original);
36 let decoded = base32_decode(&encoded).unwrap();
37 assert_eq!(decoded, original);
38 }
39
40 #[test]
41 fn base32_empty() {
42 let encoded = base32_encode(&[]);
43 assert_eq!(encoded, "");
44 let decoded = base32_decode("").unwrap();
45 assert!(decoded.is_empty());
46 }
47
48 #[test]
49 fn base32_decode_invalid_char() {
50 let result = base32_decode("!!!invalid!!!");
51 assert!(result.is_err());
52 }
53
54 #[test]
55 fn parse_node_id_invalid_base32() {
56 let result = parse_node_id("!!!not-base32!!!");
57 assert!(result.is_err());
58 }
59
60 #[test]
61 fn parse_node_id_wrong_length() {
62 let result = parse_node_id("aa");
63 assert!(result.is_err());
64 }
65}