use crate::{IntoName, Name};
use anyhow::{Context, Result};
pub struct NameBuilderOpts {
ndots: u8,
search_domain: Name,
}
impl NameBuilderOpts {
pub fn new<T: IntoName>(ndots: u8, search_domain: T) -> Result<Self> {
let search_domain = search_domain
.into_name()
.context("failed to parse search domain name")?;
Ok(NameBuilderOpts { ndots, search_domain })
}
#[cfg(feature = "hostname")]
pub fn from_hostname(ndots: u8) -> Result<Self> {
use std::str::FromStr;
let hostname = hostname::get()
.context("failed to get local hostname")?
.to_string_lossy()
.to_string();
let name = Name::from_str(&hostname).context("failed to parse local hostname")?;
let search_domain = name.base_name();
NameBuilderOpts::new(ndots, search_domain)
}
}
impl Default for NameBuilderOpts {
fn default() -> Self {
NameBuilderOpts::new(1, Name::root()).unwrap()
}
}
pub struct NameBuilder {
config: NameBuilderOpts,
}
impl NameBuilder {
pub fn new(config: NameBuilderOpts) -> NameBuilder {
NameBuilder { config }
}
pub fn from_str(&self, name: &str) -> Result<Name> {
let mut domain_name: Name = name.into_name().context("failed to parse domain name")?;
let domain_name = if domain_name.num_labels() > self.config.ndots {
domain_name.set_fqdn(true);
domain_name
} else {
domain_name.append_domain(&self.config.search_domain)?
};
Ok(domain_name)
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn name_builder_1ndots_0dot() {
let config = NameBuilderOpts::new(1, "example.com").unwrap();
let builder = NameBuilder::new(config);
let name = builder.from_str("www").unwrap();
assert_eq!(name, Name::from_ascii("www.example.com.").unwrap())
}
#[test]
fn name_builder_1ndots_1dot() {
let config = NameBuilderOpts::new(1, "example.com").unwrap();
let builder = NameBuilder::new(config);
let name = builder.from_str("www.").unwrap();
assert_eq!(name, Name::from_ascii("www.example.com.").unwrap())
}
#[test]
fn name_builder_1ndots_1dot_2lables() {
let config = NameBuilderOpts::new(1, "example.com").unwrap();
let builder = NameBuilder::new(config);
let name = builder.from_str("www.test").unwrap();
assert_eq!(name, Name::from_ascii("www.test.").unwrap())
}
#[test]
fn name_builder_1ndots_1dot_3lables() {
let config = NameBuilderOpts::new(1, "example.com").unwrap();
let builder = NameBuilder::new(config);
let name = builder.from_str("www.test.com").unwrap();
assert_eq!(name, Name::from_ascii("www.test.com.").unwrap())
}
}