use core::{fmt, ops::Deref};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{
error::ProtoResult,
rr::{RData, RecordData, RecordType, domain::Name},
serialize::binary::*,
};
macro_rules! name_rdata {
($name: ident, $rdata_policy: expr) => {
#[doc = stringify!(new type for the RecordData of $name)]
#[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
#[derive(Debug, PartialEq, Eq, Hash, Clone)]
pub struct $name(pub Name);
impl BinEncodable for $name {
fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
let mut encoder = encoder.with_rdata_behavior($rdata_policy);
self.0.emit(&mut encoder)
}
}
impl<'r> BinDecodable<'r> for $name {
fn read(decoder: &mut BinDecoder<'r>) -> Result<Self, DecodeError> {
Name::read(decoder).map(Self)
}
}
impl RecordData for $name {
fn try_borrow(data: &RData) -> Option<&Self> {
match data {
RData::$name(data) => Some(data),
_ => None,
}
}
fn record_type(&self) -> RecordType {
RecordType::$name
}
fn into_rdata(self) -> RData {
RData::$name(self)
}
}
impl Deref for $name {
type Target = Name;
fn deref(&self) -> &Self::Target {
&self.0
}
}
impl fmt::Display for $name {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{}", self.0)
}
}
};
}
name_rdata!(CNAME, RDataEncoding::StandardRecord);
name_rdata!(NS, RDataEncoding::StandardRecord);
name_rdata!(PTR, RDataEncoding::StandardRecord);
name_rdata!(ANAME, RDataEncoding::Other);
#[cfg(test)]
mod tests {
use alloc::string::ToString;
use super::*;
#[test]
fn test_it_to_string_should_not_stack_overflow() {
assert_eq!(PTR("abc.com".parse().unwrap()).to_string(), "abc.com");
}
}