use alloc::string::ToString;
use core::str::FromStr;
mod errors;
pub use errors::{LexerError, ParseError, ParseResult};
#[cfg(feature = "__dnssec")]
pub mod trust_anchor;
#[cfg(feature = "std")]
mod zone;
#[cfg(feature = "std")]
pub use zone::Parser;
mod zone_lex;
pub(crate) use zone_lex::Lexer;
pub use zone_lex::Token;
pub fn parse_ttl(ttl_str: &str) -> ParseResult<u32> {
if ttl_str.is_empty() {
return Err(ParseError::ParseTime(ttl_str.to_string()));
}
let (mut state, mut value) = (None, 0_u32);
for (i, c) in ttl_str.char_indices() {
let start = match (state, c) {
(None, '0'..='9') => {
state = Some(i);
continue;
}
(Some(_), '0'..='9') => continue,
(Some(start), 'S' | 's' | 'M' | 'm' | 'H' | 'h' | 'D' | 'd' | 'W' | 'w') => start,
_ => return Err(ParseError::ParseTime(ttl_str.to_string())),
};
let number = u32::from_str(&ttl_str[start..i])
.map_err(|_| ParseError::ParseTime(ttl_str.to_string()))?;
let multiplier = match c {
'S' | 's' => 1,
'M' | 'm' => 60,
'H' | 'h' => 3_600,
'D' | 'd' => 86_400,
'W' | 'w' => 604_800,
_ => unreachable!(),
};
value = number
.checked_mul(multiplier)
.and_then(|add| value.checked_add(add))
.ok_or_else(|| ParseError::ParseTime(ttl_str.to_string()))?;
state = None;
}
if let Some(start) = state {
let number = u32::from_str(&ttl_str[start..])
.map_err(|_| ParseError::ParseTime(ttl_str.to_string()))?;
value = value
.checked_add(number)
.ok_or_else(|| ParseError::ParseTime(ttl_str.to_string()))?;
}
Ok(value)
}