use anyhow::Result;
use rsdns::records::data;
use std::fmt::Write;
macro_rules! obsolete {
($RR:ident) => {
impl<W: Write> RDataFormatter<W, data::$RR> for RDataFmt {
fn fmt(w: &mut W, _d: &data::$RR) -> Result<()> {
write!(w, "OBSOLETE RTYPE")?;
Ok(())
}
}
};
}
fn str_from_text(text: &[u8]) -> &str {
match std::str::from_utf8(text) {
Ok(s) => s,
Err(_) => "__CH4_NON_UTF8_STRING__",
}
}
pub trait RDataFormatter<W: Write, D: data::RData> {
fn fmt(w: &mut W, d: &D) -> Result<()>;
}
pub struct RDataFmt;
impl<W: Write> RDataFormatter<W, data::A> for RDataFmt {
fn fmt(w: &mut W, d: &data::A) -> Result<()> {
write!(w, "{}", d.address)?;
Ok(())
}
}
impl<W: Write> RDataFormatter<W, data::Ns> for RDataFmt {
fn fmt(w: &mut W, d: &data::Ns) -> Result<()> {
write!(w, "{}", d.nsdname)?;
Ok(())
}
}
obsolete!(Md);
obsolete!(Mf);
impl<W: Write> RDataFormatter<W, data::Cname> for RDataFmt {
fn fmt(w: &mut W, d: &data::Cname) -> Result<()> {
write!(w, "{}", d.cname)?;
Ok(())
}
}
impl<W: Write> RDataFormatter<W, data::Soa> for RDataFmt {
fn fmt(w: &mut W, d: &data::Soa) -> Result<()> {
write!(
w,
"{} {} {} {} {} {} {}",
d.mname, d.rname, d.serial, d.refresh, d.retry, d.expire, d.minimum,
)?;
Ok(())
}
}
obsolete!(Mb);
obsolete!(Mg);
obsolete!(Mr);
obsolete!(Null);
obsolete!(Wks);
impl<W: Write> RDataFormatter<W, data::Ptr> for RDataFmt {
fn fmt(w: &mut W, d: &data::Ptr) -> Result<()> {
write!(w, "{}", d.ptrdname)?;
Ok(())
}
}
impl<W: Write> RDataFormatter<W, data::Hinfo> for RDataFmt {
fn fmt(w: &mut W, d: &data::Hinfo) -> Result<()> {
write!(
w,
"\"{}\" \"{}\"",
str_from_text(&d.cpu),
str_from_text(&d.os)
)?;
Ok(())
}
}
obsolete!(Minfo);
impl<W: Write> RDataFormatter<W, data::Mx> for RDataFmt {
fn fmt(w: &mut W, d: &data::Mx) -> Result<()> {
write!(w, "{} {}", d.preference, d.exchange)?;
Ok(())
}
}
impl<W: Write> RDataFormatter<W, data::Txt> for RDataFmt {
fn fmt(w: &mut W, d: &data::Txt) -> Result<()> {
let utf8 = str_from_text(&d.text);
write!(w, "\"{utf8}\"")?;
Ok(())
}
}
impl<W: Write> RDataFormatter<W, data::Aaaa> for RDataFmt {
fn fmt(w: &mut W, d: &data::Aaaa) -> Result<()> {
write!(w, "{}", d.address)?;
Ok(())
}
}