use bytes::Bytes; use crate::errors::*; use crate::ser::packet::{DnsPacketData, DnsPacketWriteContext}; use crate::ser::text::{DnsTextData, DnsTextFormatter, DnsTextContext, next_field, parse_with}; use std::fmt; use std::io::Cursor; use std::ops::{Deref, DerefMut}; use std::str::FromStr; use super::{DnsName, DnsNameIterator, DnsLabelRef}; /// names that should be written in canonical form for DNSSEC according /// to https://tools.ietf.org/html/rfc4034#section-6.2 /// /// DnsCompressedName always needs to be written in canonical form for /// DNSSEC. #[derive(Clone)] pub struct DnsCanonicalName(pub DnsName); impl DnsCanonicalName { /// Create new name representing the DNS root (".") pub fn new_root() -> Self { DnsCanonicalName(DnsName::new_root()) } /// Parse text representation of a domain name pub fn parse(context: &DnsTextContext, value: &str) -> Result { Ok(DnsCanonicalName(DnsName::parse(context, value)?)) } } impl Deref for DnsCanonicalName { type Target = DnsName; fn deref(&self) -> &Self::Target { &self.0 } } impl DerefMut for DnsCanonicalName { fn deref_mut(&mut self) -> &mut Self::Target { &mut self.0 } } impl AsRef for DnsCanonicalName { fn as_ref(&self) -> &DnsName { &self.0 } } impl AsMut for DnsCanonicalName { fn as_mut(&mut self) -> &mut DnsName { &mut self.0 } } impl<'a> IntoIterator for &'a DnsCanonicalName { type Item = DnsLabelRef<'a>; type IntoIter = DnsNameIterator<'a>; fn into_iter(self) -> Self::IntoIter { self.labels() } } impl PartialEq for DnsCanonicalName { fn eq(&self, rhs: &DnsName) -> bool { let this: &DnsName = self; this == rhs } } impl PartialEq for DnsCanonicalName where T: AsRef { fn eq(&self, rhs: &T) -> bool { let this: &DnsName = self.as_ref(); this == rhs } } impl Eq for DnsCanonicalName{} impl fmt::Debug for DnsCanonicalName { fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(w) } } impl fmt::Display for DnsCanonicalName { fn fmt(&self, w: &mut fmt::Formatter) -> fmt::Result { self.0.fmt(w) } } impl FromStr for DnsCanonicalName { type Err = ::failure::Error; fn from_str(s: &str) -> Result { parse_with(s, |data| DnsCanonicalName::dns_parse(&DnsTextContext::new(), data)) } } impl DnsTextData for DnsCanonicalName { fn dns_parse(context: &DnsTextContext, data: &mut &str) -> Result { let field = next_field(data)?; DnsCanonicalName::parse(context, field) } fn dns_format(&self, f: &mut DnsTextFormatter) -> fmt::Result { self.0.dns_format(f) } } impl DnsPacketData for DnsCanonicalName { fn deserialize(data: &mut Cursor) -> Result { Ok(DnsCanonicalName(super::name_packet_parser::deserialize_name(data, false)?)) } fn serialize(&self, context: &mut DnsPacketWriteContext, packet: &mut Vec) -> Result<()> { context.write_canonical_name(packet, self) } }