diff --git a/crates/net/dns/src/tree.rs b/crates/net/dns/src/tree.rs index 5520f606a..5e4bf20dd 100644 --- a/crates/net/dns/src/tree.rs +++ b/crates/net/dns/src/tree.rs @@ -179,12 +179,17 @@ impl BranchEntry { /// /// Caution: This assumes the prefix is already removed. fn parse_value(input: &str) -> ParseEntryResult { + #[inline] fn ensure_valid_hash(hash: &str) -> ParseEntryResult { - let decoded_len = BASE32_NOPAD.decode_len(hash.as_bytes().len()).map_err(|err| { - ParseDnsEntryError::Base32DecodeError(format!( - "invalid base32 child {hash} in branch: {err}" - )) - })?; + /// Returns the maximum length in bytes of the no-padding decoded data corresponding to + /// `n` bytes of base32-encoded data. + /// See also + #[inline(always)] + fn base32_no_padding_decoded_len(n: usize) -> usize { + n * 5 / 8 + } + + let decoded_len = base32_no_padding_decoded_len(hash.bytes().len()); if !(12..=32).contains(&decoded_len) || hash.chars().any(|c| c.is_whitespace()) { return Err(ParseDnsEntryError::InvalidChildHash(hash.to_string())) } @@ -353,6 +358,19 @@ mod tests { _ => unreachable!(), } } + #[test] + fn parse_branch_entry_base32() { + let s = "enrtree-branch:YNEGZIWHOM7TOOSUATAPTM"; + let entry: BranchEntry = s.parse().unwrap(); + assert_eq!(entry.to_string(), s); + + match s.parse::>().unwrap() { + DnsEntry::Branch(entry) => { + assert_eq!(entry.to_string(), s); + } + _ => unreachable!(), + } + } #[test] fn parse_invalid_branch_entry() {