add Present trait for printing Records as zonefile

This commit is contained in:
Terts Diepraam
2024-08-30 16:31:48 +02:00
parent ae9e37966e
commit a4efde7db5
24 changed files with 554 additions and 4 deletions
+48 -1
View File
@@ -201,6 +201,24 @@ macro_rules! int_enum_str_decimal {
impl core::fmt::Display for $ianatype {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
use std::fmt::Write;
write!(f, "{}", self.to_int())?;
if let Some(m) = self.to_mnemonic() {
write!(f, "(")?;
for ch in m {
f.write_char(*ch as char)?;
}
write!(f, ")")?;
}
Ok(())
}
}
impl $crate::zonefile::present::Present for $ianatype {
fn present(&self, f: &mut $crate::zonefile::present::ZoneFileFormatter) -> core::fmt::Result {
use std::fmt::Write;
write!(f, "{}", self.to_int())
}
}
@@ -275,6 +293,26 @@ macro_rules! int_enum_str_with_decimal {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
use core::fmt::Write;
match self.to_mnemonic() {
Some(m) => {
for ch in m {
f.write_char(*ch as char)?
}
write!(f, "({})", self.to_int())
}
None => {
write!(f, "{}", self.to_int())
}
}
}
}
impl $crate::zonefile::present::Present for $ianatype {
fn present(
&self,
f: &mut $crate::zonefile::present::ZoneFileFormatter<'_>,
) -> core::fmt::Result {
use std::fmt::Write;
match self.to_mnemonic() {
Some(m) => {
for ch in m {
@@ -389,7 +427,16 @@ macro_rules! int_enum_str_with_prefix {
impl core::fmt::Display for $ianatype {
fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result {
use core::fmt::Write;
$crate::zonefile::present::Present::write_presentation(self, f)
}
}
impl $crate::zonefile::present::Present for $ianatype {
fn present(
&self,
f: &mut $crate::zonefile::present::ZoneFileFormatter<'_>,
) -> core::fmt::Result {
use std::fmt::Write;
match self.to_mnemonic() {
Some(m) => {
+1 -1
View File
@@ -116,4 +116,4 @@ int_enum! {
(PRIVATEOID => 254, b"PRIVATEOID")
}
int_enum_str_with_decimal!(SecAlg, u8, "unknown algorithm");
int_enum_str_decimal!(SecAlg, u8);
+11
View File
@@ -47,6 +47,7 @@ use super::rdata::{ComposeRecordData, ParseRecordData, RecordData};
use super::record::{Record, Ttl};
use super::wire::{Compose, Composer, FormError, ParseError};
use crate::utils::base16;
use crate::zonefile::present::{Present, ZoneFileFormatter};
use core::cmp::Ordering;
use core::marker::PhantomData;
use core::{fmt, hash, mem};
@@ -358,6 +359,16 @@ impl<Octs: AsRef<[u8]> + ?Sized> fmt::Debug for Opt<Octs> {
}
}
//--- Present
impl<Octs: AsRef<[u8]> + ?Sized> Present for Opt<Octs> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
// XXX TODO Print this properly.
use std::fmt::Write;
f.write_str("OPT ...")
}
}
//------------ OptHeader -----------------------------------------------------
/// The header of an OPT record.
+14
View File
@@ -20,6 +20,7 @@ use super::iana::Rtype;
use super::scan::{Scan, Scanner, ScannerError, Symbol};
use super::wire::{Compose, Composer, ParseError};
use crate::utils::base16;
use crate::zonefile::present::{Present, ZoneFileFormatter};
use core::cmp::Ordering;
use core::fmt;
use octseq::octets::{Octets, OctetsFrom};
@@ -477,6 +478,19 @@ impl<Octs: AsRef<[u8]>> fmt::Debug for UnknownRecordData<Octs> {
}
}
//--- Present
impl<Octs: AsRef<[u8]>> Present for UnknownRecordData<Octs> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "\\# {}", self.data.as_ref().len())?;
for ch in self.data.as_ref() {
write!(f, " {:02x}", *ch)?
}
Ok(())
}
}
//============ Errors ========================================================
//------------ LongRecordData ------------------------------------------------
+29
View File
@@ -15,6 +15,8 @@
//! [`RecordHeader`]: struct.RecordHeader.html
//! [`ParsedRecord`]: struct.ParsedRecord.html
use crate::zonefile::present::{Present, ZoneFileFormatter};
use super::cmp::CanonicalOrd;
use super::iana::{Class, Rtype};
use super::name::{FlattenInto, ParsedName, ToName};
@@ -431,6 +433,26 @@ where
}
}
//--- Present
impl<Name, Data> Present for Record<Name, Data>
where
Name: fmt::Display,
Data: RecordData + Present,
{
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{} ", self.owner)?;
self.ttl.present(f)?;
f.write_char(' ')?;
self.class.present(f)?;
f.write_char(' ')?;
self.data.rtype().present(f)?;
f.write_char(' ')?;
self.data.present(f)
}
}
//------------ ComposeRecord -------------------------------------------------
/// A helper trait allowing construction of records on the fly.
@@ -1481,6 +1503,13 @@ impl Ttl {
}
}
impl Present for Ttl {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{}", self.as_secs())
}
}
impl core::ops::Add for Ttl {
type Output = Ttl;
+10
View File
@@ -10,6 +10,7 @@ use crate::base::net::Ipv6Addr;
use crate::base::rdata::{ComposeRecordData, ParseRecordData, RecordData};
use crate::base::scan::{Scanner, ScannerError};
use crate::base::wire::{Composer, Parse, ParseError};
use crate::zonefile::present::Present;
use core::cmp::Ordering;
use core::convert::Infallible;
use core::str::FromStr;
@@ -156,6 +157,15 @@ impl fmt::Display for Aaaa {
}
}
//--- Present
impl Present for Aaaa {
fn present(&self, f: &mut crate::zonefile::present::ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{}", self.addr)
}
}
//--- AsRef and AsMut
impl AsRef<Ipv6Addr> for Aaaa {
+30
View File
@@ -9,6 +9,7 @@ use crate::base::rdata::{
use crate::base::scan::{Scan, Scanner, ScannerError};
use crate::base::wire::{Compose, Composer, Parse, ParseError};
use crate::utils::{base16, base64};
use crate::zonefile::present::{Present, ZoneFileFormatter};
use core::cmp::Ordering;
use core::{fmt, hash};
use octseq::octets::{Octets, OctetsFrom, OctetsInto};
@@ -319,6 +320,18 @@ impl<Octs: AsRef<[u8]>> fmt::Debug for Cdnskey<Octs> {
}
}
//--- Present
impl<Octs: AsRef<[u8]>> Present for Cdnskey<Octs> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{} {} ", self.flags, self.protocol)?;
self.algorithm.present(f)?;
f.write_char(' ')?;
base64::display(&self.public_key, f)
}
}
//------------ Cds -----------------------------------------------------------
#[derive(Clone)]
@@ -646,6 +659,23 @@ impl<Octs: AsRef<[u8]>> fmt::Debug for Cds<Octs> {
}
}
//--- Present
impl<Octs: AsRef<[u8]>> Present for Cds<Octs> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(
f,
"{} {} {} ",
self.key_tag, self.algorithm, self.digest_type
)?;
for ch in self.digest.as_ref() {
write!(f, "{:02x}", ch)?
}
Ok(())
}
}
//------------ parsed --------------------------------------------------------
pub mod parsed {
+79 -2
View File
@@ -15,6 +15,7 @@ use crate::base::serial::Serial;
use crate::base::wire::{Compose, Composer, FormError, Parse, ParseError};
use crate::base::Ttl;
use crate::utils::{base16, base64};
use crate::zonefile::present::{Present, ZoneFileFormatter};
use core::cmp::Ordering;
use core::convert::TryInto;
use core::{cmp, fmt, hash, str};
@@ -431,6 +432,18 @@ impl<Octs: AsRef<[u8]>> fmt::Debug for Dnskey<Octs> {
}
}
//--- Present
impl<Octs: AsRef<[u8]>> Present for Dnskey<Octs> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{} {} ", self.flags, self.protocol)?;
self.algorithm.present(f)?;
f.write_char(' ')?;
base64::display(&self.public_key, f)
}
}
//------------ ProtoRrsig ----------------------------------------------------
/// The RRSIG RDATA to be included when creating the signature.
@@ -757,6 +770,15 @@ impl fmt::Display for Timestamp {
}
}
//--- Present
impl Present for Timestamp {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{}", self.0)
}
}
//--- PartialOrd and CanonicalOrd
impl cmp::PartialOrd for Timestamp {
@@ -1354,6 +1376,30 @@ where
}
}
//--- Present
impl<Octs, Name> Present for Rrsig<Octs, Name>
where
Octs: AsRef<[u8]>,
Name: fmt::Display,
{
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
self.type_covered.present(f)?;
f.write_char(' ')?;
self.algorithm.present(f)?;
f.write_char(' ')?;
self.original_ttl.present(f)?;
f.write_char(' ')?;
self.expiration.present(f)?;
f.write_char(' ')?;
self.inception.present(f)?;
f.write_char(' ')?;
write!(f, " {} {}. ", self.key_tag, self.signer_name)?;
base64::display(&self.signature, f)
}
}
//------------ Nsec ----------------------------------------------------------
#[derive(Clone)]
@@ -1634,6 +1680,19 @@ where
}
}
//--- Present
impl<Octs, Name> Present for Nsec<Octs, Name>
where
Octs: AsRef<[u8]>,
Name: fmt::Display,
{
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{}. {}", self.next_name, self.types)
}
}
//------------ Ds -----------------------------------------------------------
#[derive(Clone)]
@@ -1945,7 +2004,7 @@ impl<Octs: AsRef<[u8]>> fmt::Display for Ds<Octs> {
write!(
f,
"{} {} {} ",
self.key_tag, self.algorithm.to_int(), self.digest_type
self.key_tag, self.algorithm, self.digest_type
)?;
for ch in self.digest.as_ref() {
write!(f, "{:02x}", ch)?
@@ -1967,6 +2026,24 @@ impl<Octs: AsRef<[u8]>> fmt::Debug for Ds<Octs> {
}
}
//--- Present
impl<Octs: AsRef<[u8]>> Present for Ds<Octs> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{} ", self.key_tag)?;
self.algorithm.present(f)?;
f.write_char(' ')?;
self.digest_type.present(f)?;
f.write_char(' ')?;
for ch in self.digest.as_ref() {
write!(f, "{:02x}", ch)?
}
Ok(())
}
}
//------------ RtypeBitmap ---------------------------------------------------
#[derive(Clone)]
@@ -2432,7 +2509,7 @@ where
let buf_len = self.buf.as_ref().len();
for src_pos in (0..buf_len).step_by(34) {
let chunk_len = (self.buf.as_ref()[src_pos + 1] as usize) + 2;
let buf = self.buf.as_mut();
let buf = self.buf.as_mut();
buf.copy_within(src_pos..src_pos+chunk_len, dst_pos);
dst_pos += chunk_len;
}
+50
View File
@@ -499,6 +499,25 @@ macro_rules! rdata_types {
}
}
///--- Present
impl<O, N> $crate::zonefile::present::Present for ZoneRecordData<O, N>
where
O: AsRef<[u8]>,
N: fmt::Display
{
fn present(&self, f: &mut $crate::zonefile::present::ZoneFileFormatter) -> fmt::Result {
match *self {
$( $( $(
ZoneRecordData::$mtype(ref inner) => {
inner.present(f)
}
)* )* )*
ZoneRecordData::Unknown(ref inner) => inner.present(f),
}
}
}
//------------- AllRecordData ----------------------------------------
/// Record data for all record types.
@@ -1102,6 +1121,28 @@ macro_rules! rdata_types {
}
}
//--- Present
impl<O, N> $crate::zonefile::present::Present for AllRecordData<O, N>
where O: Octets, N: fmt::Display {
fn present(
&self, f: &mut $crate::zonefile::present::ZoneFileFormatter
) -> fmt::Result {
match *self {
$( $( $(
AllRecordData::$mtype(ref inner) => {
inner.present(f)
}
)* )* )*
$( $( $(
AllRecordData::$ptype(ref inner) => {
inner.present(f)
}
)* )* )*
AllRecordData::Opt(ref inner) => inner.present(f),
AllRecordData::Unknown(ref inner) => inner.present(f),
}
}
}
}
}
@@ -1288,6 +1329,15 @@ macro_rules! name_type_base {
write!(f, "{}.", self.$field)
}
}
//--- Present
impl<N: fmt::Display> $crate::zonefile::present::Present for $target<N> {
fn present(&self, f: &mut $crate::zonefile::present::ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{}.", self.$field)
}
}
}
}
+41
View File
@@ -13,6 +13,7 @@ use crate::base::scan::{
};
use crate::base::wire::{Compose, Composer, Parse, ParseError};
use crate::utils::{base16, base32};
use crate::zonefile::present::{Present, ZoneFileFormatter};
#[cfg(feature = "bytes")]
use bytes::Bytes;
use core::cmp::Ordering;
@@ -369,6 +370,27 @@ impl<Octs: AsRef<[u8]>> fmt::Debug for Nsec3<Octs> {
}
}
//--- Present
//--- Present
impl<Octs: AsRef<[u8]>> Present for Nsec3<Octs>
where
Octs: AsRef<[u8]>,
{
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
self.hash_algorithm.present(f)?;
write!(f, " {} {} ", self.flags, self.iterations)?;
self.salt.present(f)?;
f.write_char(' ')?;
base32::display_hex(&self.next_owner, f)?;
write!(f, " {}", self.types)
}
}
//------------ Nsec3Param ----------------------------------------------------
#[derive(Clone)]
@@ -661,6 +683,17 @@ impl<Octs: AsRef<[u8]>> fmt::Debug for Nsec3param<Octs> {
}
}
//--- Present
impl<Octs: AsRef<[u8]>> Present for Nsec3param<Octs> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
self.hash_algorithm.present(f)?;
write!(f, " {} {} ", self.flags, self.iterations)?;
self.salt.present(f)
}
}
//------------ Nsec3Salt -----------------------------------------------------
/// The salt value of an NSEC3 record.
@@ -970,6 +1003,14 @@ impl<Octs: AsRef<[u8]> + ?Sized> fmt::Debug for Nsec3Salt<Octs> {
}
}
//--- Present
impl<Octs: AsRef<[u8]> + ?Sized> Present for Nsec3Salt<Octs> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
base16::display(self.as_slice(), f)
}
}
//--- Serialize and Deserialize
#[cfg(feature = "serde")]
+10
View File
@@ -10,6 +10,7 @@ use crate::base::rdata::{
};
use crate::base::scan::{Scanner, ScannerError};
use crate::base::wire::{Composer, Parse, ParseError};
use crate::zonefile::present::{Present, ZoneFileFormatter};
use core::{fmt, str};
use core::cmp::Ordering;
use core::convert::Infallible;
@@ -172,6 +173,15 @@ impl fmt::Display for A {
}
}
//--- Display
impl Present for A {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{}", self.addr)
}
}
//--- AsRef and AsMut
impl AsRef<Ipv4Addr> for A {
+10
View File
@@ -10,6 +10,7 @@ use crate::base::rdata::{
};
use crate::base::scan::Scanner;
use crate::base::wire::{Composer, ParseError};
use crate::zonefile::present::{Present, ZoneFileFormatter};
use core::{fmt, hash};
use core::cmp::Ordering;
#[cfg(feature = "serde")]
@@ -236,6 +237,15 @@ impl<Octs: AsRef<[u8]>> fmt::Debug for Hinfo<Octs> {
}
}
//--- Present
impl<Octs: AsRef<[u8]>> Present for Hinfo<Octs> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{} {}", self.cpu, self.os)
}
}
//============ Testing =======================================================
#[cfg(test)]
+10
View File
@@ -10,6 +10,7 @@ use crate::base::rdata::{
};
use crate::base::scan::Scanner;
use crate::base::wire::{Composer, ParseError};
use crate::zonefile::present::{Present, ZoneFileFormatter};
use core::fmt;
use core::cmp::Ordering;
use octseq::octets::{Octets, OctetsFrom, OctetsInto};
@@ -242,6 +243,15 @@ impl<N: fmt::Display> fmt::Display for Minfo<N> {
}
}
//--- Present
impl<N: fmt::Display> Present for Minfo<N> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{}. {}.", self.rmailbx, self.emailbx)
}
}
//============ Testing =======================================================
#[cfg(test)]
+10
View File
@@ -10,6 +10,7 @@ use crate::base::rdata::{
};
use crate::base::scan::{Scan, Scanner};
use crate::base::wire::{Compose, Composer, Parse, ParseError};
use crate::zonefile::present::{Present, ZoneFileFormatter};
use core::fmt;
use core::cmp::Ordering;
use octseq::octets::{Octets, OctetsFrom, OctetsInto};
@@ -227,6 +228,15 @@ impl<N: fmt::Display> fmt::Display for Mx<N> {
}
}
//--- Present
impl<N: fmt::Display> Present for Mx<N> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{} {}.", self.preference, self.exchange)
}
}
//============ Testing =======================================================
#[cfg(test)]
+14
View File
@@ -8,6 +8,7 @@ use crate::base::rdata::{
ComposeRecordData, LongRecordData, ParseRecordData, RecordData,
};
use crate::base::wire::{Composer, ParseError};
use crate::zonefile::present::{Present, ZoneFileFormatter};
use core::{fmt, hash, mem};
use core::cmp::Ordering;
use octseq::octets::{Octets, OctetsFrom, OctetsInto};
@@ -277,6 +278,19 @@ impl<Octs: AsRef<[u8]>> fmt::Debug for Null<Octs> {
}
}
//--- Present
impl<Octs: AsRef<[u8]>> Present for Null<Octs> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "\\# {}", self.data.as_ref().len())?;
for ch in self.data.as_ref().iter() {
write!(f, " {:02x}", ch)?;
}
Ok(())
}
}
//============ Testing =======================================================
#[cfg(test)]
+18
View File
@@ -12,6 +12,7 @@ use crate::base::record::Ttl;
use crate::base::scan::{Scan, Scanner};
use crate::base::serial::Serial;
use crate::base::wire::{Compose, Composer, ParseError};
use crate::zonefile::present::{Present, ZoneFileFormatter};
use core::fmt;
use core::cmp::Ordering;
use octseq::octets::{Octets, OctetsFrom, OctetsInto};
@@ -401,6 +402,23 @@ impl<N: fmt::Display> fmt::Display for Soa<N> {
}
}
impl<N: fmt::Display> Present for Soa<N> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(
f,
"{}. {}. {} {} {} {} {}",
self.mname,
self.rname,
self.serial,
self.refresh.as_secs(),
self.retry.as_secs(),
self.expire.as_secs(),
self.minimum.as_secs()
)
}
}
//============ Testing =======================================================
#[cfg(test)]
+19
View File
@@ -14,6 +14,7 @@ use crate::base::scan::Scanner;
#[cfg(feature = "serde")]
use crate::base::scan::Symbol;
use crate::base::wire::{Composer, FormError, ParseError};
use crate::zonefile::present::{Present, ZoneFileFormatter};
#[cfg(feature = "bytes")]
use bytes::BytesMut;
use core::cmp::Ordering;
@@ -464,6 +465,24 @@ impl<Octs: AsRef<[u8]>> fmt::Debug for Txt<Octs> {
}
}
//--- Present
impl<Octs: AsRef<[u8]>> Present for Txt<Octs> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
let mut first = true;
for slice in self.iter_charstrs() {
if !first {
f.write_str(" ")?;
} else {
first = false;
}
write!(f, "{}", slice.display_quoted())?;
}
Ok(())
}
}
//--- Serialize and Deserialize
#[cfg(feature = "serde")]
+14
View File
@@ -10,6 +10,7 @@ use crate::base::name::{FlattenInto, ParsedName, ToName};
use crate::base::rdata::{ComposeRecordData, ParseRecordData, RecordData};
use crate::base::scan::{Scan, Scanner};
use crate::base::wire::{Compose, Composer, Parse, ParseError};
use crate::zonefile::present::{Present, ZoneFileFormatter};
use core::cmp::Ordering;
use core::fmt;
use octseq::octets::{Octets, OctetsFrom, OctetsInto};
@@ -282,6 +283,19 @@ impl<N: fmt::Display> fmt::Display for Srv<N> {
}
}
//--- Present
impl<N: fmt::Display> Present for Srv<N> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(
f,
"{} {} {} {}",
self.priority, self.weight, self.port, self.target
)
}
}
//============ Testing ======================================================
#[cfg(test)]
+31
View File
@@ -7,6 +7,7 @@ use crate::base::cmp::CanonicalOrd;
use crate::base::iana::SvcParamKey;
use crate::base::scan::Symbol;
use crate::base::wire::{Compose, Parse, ParseError};
use crate::zonefile::present::{Present, ZoneFileFormatter};
use octseq::builder::{EmptyBuilder, FromBuilder, OctetsBuilder, ShortBuf};
use octseq::octets::{Octets, OctetsFrom, OctetsInto};
use octseq::parse::{Parser, ShortInput};
@@ -361,6 +362,36 @@ impl<Octs: Octets + ?Sized> fmt::Debug for SvcParams<Octs> {
}
}
//-- Present
impl<Octs: Octets + ?Sized> Present for SvcParams<Octs> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
let mut parser = Parser::from_ref(self.as_slice());
let mut first = true;
while parser.remaining() > 0 {
let key = SvcParamKey::parse(
&mut parser
).expect("invalid SvcbParam");
let len = usize::from(
u16::parse(&mut parser).expect("invalid SvcParam")
);
let mut parser = parser.parse_parser(
len
).expect("invalid SvcParam");
if first {
first = false;
}
else {
f.write_str(" ")?;
}
write!(
f, "{}", super::value::AllValues::parse_any(key, &mut parser)
)?;
};
Ok(())
}
}
//------------ ValueIter -----------------------------------------------------
+15
View File
@@ -10,6 +10,7 @@ use crate::base::rdata::{
ComposeRecordData, LongRecordData, ParseRecordData, RecordData,
};
use crate::base::wire::{Compose, Composer, Parse, ParseError};
use crate::zonefile::present::{Present, ZoneFileFormatter};
use octseq::octets::{Octets, OctetsFrom, OctetsInto};
use octseq::parse::Parser;
use core::{cmp, fmt, hash};
@@ -464,6 +465,20 @@ where
}
}
//--- Present
impl<Variant, Octs, Name> Present for SvcbRdata<Variant, Octs, Name>
where
Octs: Octets,
Name: fmt::Display,
{
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(f, "{} {} ", self.priority, self.target)?;
self.params.present(f)
}
}
//============ Tests =========================================================
#[cfg(test)]
+18
View File
@@ -12,6 +12,7 @@ use crate::base::rdata::{
};
use crate::base::wire::{Compose, Composer, Parse, ParseError};
use crate::utils::base64;
use crate::zonefile::present::{Present, ZoneFileFormatter};
use core::cmp::Ordering;
use core::{fmt, hash};
use octseq::builder::OctetsBuilder;
@@ -600,6 +601,23 @@ impl<O: AsRef<[u8]>, N: fmt::Debug> fmt::Debug for Tsig<O, N> {
}
}
//--- Present
impl<O: AsRef<[u8]>, N: fmt::Display> Present for Tsig<O, N> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(
f,
"{}. {} {} ",
self.algorithm, self.time_signed, self.fudge
)?;
base64::display(&self.mac, f)?;
write!(f, " {} {} \"", self.original_id, self.error)?;
base64::display(&self.other, f)?;
write!(f, "\"")
}
}
//------------ Time48 --------------------------------------------------------
/// A 48-bit Unix timestamp.
+16
View File
@@ -11,6 +11,7 @@ use crate::base::scan::{Scan, Scanner};
use crate::base::serial::Serial;
use crate::base::wire::{Composer, ParseError};
use crate::utils::base16;
use crate::zonefile::present::{Present, ZoneFileFormatter};
use core::cmp::Ordering;
use core::{fmt, hash};
use octseq::octets::{Octets, OctetsFrom, OctetsInto};
@@ -223,6 +224,21 @@ impl<Octs: AsRef<[u8]>> fmt::Debug for Zonemd<Octs> {
}
}
impl<Octs: AsRef<[u8]>> Present for Zonemd<Octs> {
fn present(&self, f: &mut ZoneFileFormatter) -> fmt::Result {
use std::fmt::Write;
write!(
f,
"{} {} {} ( ",
self.serial,
u8::from(self.scheme),
u8::from(self.algo)
)?;
base16::display(&self.digest, f)?;
write!(f, " )")
}
}
impl<Octs, Other> PartialOrd<Zonemd<Other>> for Zonemd<Octs>
where
Octs: AsRef<[u8]>,
+1
View File
@@ -3,3 +3,4 @@
#![cfg_attr(docsrs, doc(cfg(feature = "zonefile")))]
pub mod inplace;
pub mod present;
+55
View File
@@ -0,0 +1,55 @@
//! Modelled roughly after `std::fmt::Display`
use core::fmt::{self, Write};
use std::string::String;
pub struct ZoneFileFormatter<'a> {
buf: &'a mut (dyn Write + 'a),
}
pub struct Error;
/// Print as presentation format
pub trait Present {
fn present(&self, w: &mut ZoneFileFormatter) -> fmt::Result;
fn write_presentation<W: Write>(&self, mut w: W) -> fmt::Result {
let mut formatter = ZoneFileFormatter {
buf: &mut w,
};
self.present(&mut formatter)
}
fn to_presentation_string(&self) -> String {
let mut s = String::new();
self.write_presentation(&mut s).unwrap();
s
}
}
impl ZoneFileFormatter<'_> {
pub fn format<P: Present>(&mut self, item: &P) -> fmt::Result {
item.present(self)
}
pub fn write_bytes(&mut self, b: &[u8]) -> fmt::Result {
for byte in b {
self.write_char(*byte as char)?;
}
Ok(())
}
}
impl Write for ZoneFileFormatter<'_> {
fn write_str(&mut self, s: &str) -> fmt::Result {
self.buf.write_str(s)
}
fn write_char(&mut self, c: char) -> fmt::Result {
self.buf.write_char(c)
}
fn write_fmt(&mut self, args: fmt::Arguments<'_>) -> fmt::Result {
self.buf.write_fmt(args)
}
}