use core::{fmt, ops::Deref};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
use crate::{
error::ProtoResult,
rr::{RData, RecordData, RecordType, domain::Name},
serialize::binary::*,
};
pub fn read(decoder: &mut BinDecoder<'_>) -> ProtoResult<Name> {
Name::read(decoder)
}
pub fn emit(encoder: &mut BinEncoder<'_>, name_data: &Name) -> ProtoResult<()> {
let is_canonical_names = encoder.is_canonical_names();
name_data.emit_with_lowercase(encoder, is_canonical_names)?;
Ok(())
}
macro_rules! name_rdata {
($name: ident) => {
#[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<()> {
emit(encoder, &self.0)
}
}
impl<'r> BinDecodable<'r> for $name {
fn read(decoder: &mut BinDecoder<'r>) -> ProtoResult<Self> {
Name::read(decoder).map(Self)
}
}
impl RecordData for $name {
fn try_from_rdata(data: RData) -> Result<Self, RData> {
match data {
RData::$name(data) => Ok(data),
_ => Err(data),
}
}
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);
name_rdata!(NS);
name_rdata!(PTR);
name_rdata!(ANAME);
#[cfg(test)]
mod tests {
use alloc::{string::ToString, vec::Vec};
#[cfg(feature = "std")]
use std::println;
use super::*;
#[test]
fn test_it_to_string_should_not_stack_overflow() {
assert_eq!(PTR("abc.com".parse().unwrap()).to_string(), "abc.com");
}
#[test]
fn test() {
#![allow(clippy::dbg_macro, clippy::print_stdout)]
let rdata = Name::from_ascii("WWW.example.com.").unwrap();
let mut bytes = Vec::new();
let mut encoder = BinEncoder::new(&mut bytes);
assert!(emit(&mut encoder, &rdata).is_ok());
let bytes = encoder.into_bytes();
#[cfg(feature = "std")]
println!("bytes: {bytes:?}");
let mut decoder = BinDecoder::new(bytes);
let read_rdata = read(&mut decoder).expect("Decoding error");
assert_eq!(rdata, read_rdata);
}
}