use core::cmp::Ordering;
use super::wire::{BuildBytes, TruncationError};
mod label;
pub use label::{
Label, LabelBuf, LabelIter, LabelParseError, LabelSplitError, label,
label_buf,
};
mod absolute;
pub use absolute::{Name, NameBuf, NameParseError, NameSplitError};
mod reversed;
pub use reversed::{RevName, RevNameBuf};
mod unparsed;
pub use unparsed::UnparsedName;
mod compressor;
pub use compressor::NameCompressor;
pub trait CanonicalName: BuildBytes + Ord {
fn build_lowercased_bytes<'b>(
&self,
bytes: &'b mut [u8],
) -> Result<&'b mut [u8], TruncationError> {
let rest = self.build_bytes(bytes)?.len();
let (bytes, rest) = bytes.split_at_mut(bytes.len() - rest);
bytes.make_ascii_lowercase();
Ok(rest)
}
fn cmp_composed(&self, other: &Self) -> Ordering {
let mut this = [0u8; 255];
let rest_len = self
.build_bytes(&mut this)
.expect("domain names are at most 255 bytes when serialized")
.len();
let this = &this[..this.len() - rest_len];
let mut that = [0u8; 255];
let rest_len = other
.build_bytes(&mut that)
.expect("domain names are at most 255 bytes when serialized")
.len();
let that = &that[..that.len() - rest_len];
this.cmp(that)
}
fn cmp_lowercase_composed(&self, other: &Self) -> Ordering {
let mut this = [0u8; 255];
let rest_len = self
.build_lowercased_bytes(&mut this)
.expect("domain names are at most 255 bytes when serialized")
.len();
let this = &this[..this.len() - rest_len];
let mut that = [0u8; 255];
let rest_len = other
.build_lowercased_bytes(&mut that)
.expect("domain names are at most 255 bytes when serialized")
.len();
let that = &that[..that.len() - rest_len];
this.cmp(that)
}
}
macro_rules! impl_canonical_name_for_deref {
{$(
$(#[$attr:meta])*
impl[$($args:tt)*] CanonicalName for $subject:ty;
)*} => {$(
$(#[$attr])*
impl<$($args)*> CanonicalName for $subject {
fn build_lowercased_bytes<'b>(
&self,
bytes: &'b mut [u8],
) -> Result<&'b mut [u8], TruncationError> {
(**self).build_lowercased_bytes(bytes)
}
fn cmp_composed(&self, other: &Self) -> Ordering {
(**self).cmp_composed(&**other)
}
fn cmp_lowercase_composed(&self, other: &Self) -> Ordering {
(**self).cmp_lowercase_composed(&**other)
}
}
)*};
}
impl_canonical_name_for_deref! {
impl[N: ?Sized + CanonicalName] CanonicalName for &N;
impl[N: ?Sized + CanonicalName] CanonicalName for &mut N;
#[cfg(feature = "alloc")]
impl[N: ?Sized + CanonicalName] CanonicalName for alloc::boxed::Box<N>;
#[cfg(feature = "alloc")]
impl[N: ?Sized + CanonicalName] CanonicalName for alloc::rc::Rc<N>;
#[cfg(feature = "alloc")]
impl[N: ?Sized + CanonicalName] CanonicalName for alloc::sync::Arc<N>;
}
#[cfg(feature = "alloc")]
#[cfg(test)]
mod tests {
use crate::new::base::name::CanonicalName;
use crate::new::base::wire::BuildBytes;
use super::NameBuf;
use alloc::vec;
#[test]
fn test_build_lowercased_bytes_simple() {
let name: NameBuf = "E.com.".parse().unwrap();
let mut buf = vec![0u8; name.built_bytes_size()];
assert!(name.build_lowercased_bytes(&mut buf).unwrap().is_empty());
assert_eq!(buf, buf.to_ascii_lowercase());
}
#[test]
fn test_build_lowercased_bytes_too_long_buffer() {
let name: NameBuf = "E.com.".parse().unwrap();
let mut buf = vec![0u8; 100];
let rest = name.build_lowercased_bytes(&mut buf).unwrap();
assert_eq!(rest.len(), 93);
assert_eq!(buf[..7], b"\x01e\x03com\x00"[..]);
}
}