From b7c5b4e13c7c0de42a11c1b6ff291ac4a00d4f26 Mon Sep 17 00:00:00 2001 From: Daniel Sharifi Date: Fri, 24 Jan 2025 17:15:08 +0100 Subject: [PATCH] feat: add const try_from_str constructor to DnsName type. --- src/server_name.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/server_name.rs b/src/server_name.rs index ced1554..997a226 100644 --- a/src/server_name.rs +++ b/src/server_name.rs @@ -204,6 +204,14 @@ impl<'a> DnsName<'a> { Err(_) => Err(s), } } + + /// Produces a borrowed [`DnsName`] from a borrowed [`str`]. + pub const fn try_from_str(s: &str) -> Result, InvalidDnsNameError> { + match validate(s.as_bytes()) { + Ok(_) => Ok(DnsName(DnsNameInner::Borrowed(s))), + Err(_) => Err(InvalidDnsNameError), + } + } } #[cfg(feature = "alloc")] @@ -300,7 +308,7 @@ impl fmt::Display for InvalidDnsNameError { #[cfg(feature = "std")] impl StdError for InvalidDnsNameError {} -fn validate(input: &[u8]) -> Result<(), InvalidDnsNameError> { +const fn validate(input: &[u8]) -> Result<(), InvalidDnsNameError> { enum State { Start, Next, @@ -323,7 +331,9 @@ fn validate(input: &[u8]) -> Result<(), InvalidDnsNameError> { return Err(InvalidDnsNameError); } - for ch in input { + let mut character_index = 0; + while character_index < input.len() { + let ch = input[character_index]; state = match (state, ch) { (Start | Next | NextAfterNumericOnly | Hyphen { .. }, b'.') => { return Err(InvalidDnsNameError) @@ -349,6 +359,7 @@ fn validate(input: &[u8]) -> Result<(), InvalidDnsNameError> { ) => Subsequent { len: len + 1 }, _ => return Err(InvalidDnsNameError), }; + character_index += 1; } if matches!(