#[cfg(feature = "serde")]
use alloc::string::{String, ToString};
use core::cmp::{Ordering, PartialEq};
use core::fmt;
use core::hash::{Hash, Hasher};
use core::ops::{Deref, DerefMut};
use core::str::FromStr;
use crate::error::*;
#[cfg(feature = "serde")]
use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
use crate::rr::Name;
use crate::serialize::binary::*;
#[derive(Default, Debug, Eq, Clone)]
pub struct LowerName(Name);
impl LowerName {
pub fn new(name: &Name) -> Self {
Self(name.to_lowercase())
}
pub fn is_root(&self) -> bool {
self.0.is_root()
}
pub fn is_fqdn(&self) -> bool {
self.0.is_fqdn()
}
pub fn base_name(&self) -> Self {
Self(self.0.base_name())
}
pub fn zone_of(&self, name: &Self) -> bool {
self.0.zone_of_case(&name.0)
}
pub fn num_labels(&self) -> u8 {
self.0.num_labels()
}
pub fn len(&self) -> usize {
self.0.len()
}
pub fn is_empty(&self) -> bool {
self.0.is_empty()
}
pub fn is_wildcard(&self) -> bool {
self.0.is_wildcard()
}
pub fn into_wildcard(self) -> Self {
let name = self.0.into_wildcard();
Self(name)
}
}
impl Hash for LowerName {
fn hash<H>(&self, state: &mut H)
where
H: Hasher,
{
for label in &self.0 {
state.write(label);
}
}
}
impl PartialEq<Self> for LowerName {
fn eq(&self, other: &Self) -> bool {
self.0.eq_case(&other.0)
}
}
impl BinEncodable for LowerName {
fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
self.0.emit(encoder)
}
}
impl fmt::Display for LowerName {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.0.fmt(f)
}
}
impl PartialOrd<Self> for LowerName {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(self.cmp(other))
}
}
impl Ord for LowerName {
fn cmp(&self, other: &Self) -> Ordering {
self.0.cmp_case(&other.0)
}
}
impl From<Name> for LowerName {
fn from(name: Name) -> Self {
Self::new(&name)
}
}
impl<'a> From<&'a Name> for LowerName {
fn from(name: &'a Name) -> Self {
Self::new(name)
}
}
impl From<LowerName> for Name {
fn from(name: LowerName) -> Self {
name.0
}
}
impl<'a> From<&'a LowerName> for Name {
fn from(name: &'a LowerName) -> Self {
name.0.clone()
}
}
impl Deref for LowerName {
type Target = Name;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl DerefMut for LowerName {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}
impl<'r> BinDecodable<'r> for LowerName {
fn read(decoder: &mut BinDecoder<'r>) -> Result<Self, DecodeError> {
let name = Name::read(decoder)?;
Ok(Self(name.to_lowercase()))
}
}
impl FromStr for LowerName {
type Err = ProtoError;
fn from_str(name: &str) -> Result<Self, Self::Err> {
Name::from_str(name).map(Self::from)
}
}
#[cfg(feature = "serde")]
impl Serialize for LowerName {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(&self.to_string())
}
}
#[cfg(feature = "serde")]
impl<'de> Deserialize<'de> for LowerName {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: Deserializer<'de>,
{
let s = String::deserialize(deserializer)?;
FromStr::from_str(&s).map_err(de::Error::custom)
}
}
#[test]
fn test_name_lowername_roundtrip() {
let fqdn_name = Name::from_ascii("example.com.").unwrap();
let relative_name = Name::from_ascii("example.com").unwrap();
let fqdn_lname = LowerName::from(fqdn_name.clone());
let relative_lname = LowerName::from(relative_name.clone());
let fqdn_rt_name: Name = fqdn_lname.into();
let relative_rt_name: Name = relative_lname.into();
assert_eq!(fqdn_name, fqdn_rt_name);
assert_eq!(relative_name, relative_rt_name);
assert!(fqdn_rt_name != relative_rt_name);
}