diff --git a/src/rdata/zonemd.rs b/src/rdata/zonemd.rs index 66f41d40..ed53f94d 100644 --- a/src/rdata/zonemd.rs +++ b/src/rdata/zonemd.rs @@ -13,10 +13,11 @@ use crate::base::iana::Rtype; use crate::base::rdata::{ComposeRecordData, RecordData}; use crate::base::scan::{Scan, Scanner}; use crate::base::serial::Serial; -use crate::base::zonefile_fmt::{self, Formatter, ZonefileFmt}; use crate::base::wire::{Composer, ParseError}; +use crate::base::zonefile_fmt::{self, Formatter, ZonefileFmt}; use crate::utils::base16; use core::cmp::Ordering; +use core::str::FromStr; use core::{fmt, hash}; use octseq::octets::{Octets, OctetsFrom, OctetsInto}; use octseq::parse::Parser; @@ -233,20 +234,26 @@ impl> ZonefileFmt for Zonemd { p.block(|p| { p.write_token(self.serial)?; p.write_show(self.scheme)?; - p.write_comment(format_args!("scheme ({})", match self.scheme { - Scheme::Reserved => "reserved", - Scheme::Simple => "simple", - Scheme::Unassigned(_) => "unassigned", - Scheme::Private(_) => "private", - }))?; + p.write_comment(format_args!( + "scheme ({})", + match self.scheme { + Scheme::Reserved => "reserved", + Scheme::Simple => "simple", + Scheme::Unassigned(_) => "unassigned", + Scheme::Private(_) => "private", + } + ))?; p.write_show(self.algo)?; - p.write_comment(format_args!("algorithm ({})", match self.algo { - Algorithm::Reserved => "reserved", - Algorithm::Sha384 => "SHA384", - Algorithm::Sha512 => "SHA512", - Algorithm::Unassigned(_) => "unassigned", - Algorithm::Private(_) => "private", - }))?; + p.write_comment(format_args!( + "algorithm ({})", + match self.algo { + Algorithm::Reserved => "reserved", + Algorithm::Sha384 => "SHA384", + Algorithm::Sha512 => "SHA512", + Algorithm::Unassigned(_) => "unassigned", + Algorithm::Private(_) => "private", + } + ))?; p.write_token(base16::encode_display(&self.digest)) }) } @@ -350,12 +357,41 @@ impl From for Scheme { } } +impl FromStr for Scheme { + type Err = SchemeFromStrError; + + // Only implement the actionable variants + fn from_str(s: &str) -> Result { + match s { + "1" | "SIMPLE" => Ok(Self::Simple), + _ => Err(SchemeFromStrError(())), + } + } +} + impl ZonefileFmt for Scheme { fn fmt(&self, p: &mut impl Formatter) -> zonefile_fmt::Result { p.write_token(u8::from(*self)) } } +//------------ SchemeFromStrError --------------------------------------------- + +/// An error occured while reading the scheme from a string. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct SchemeFromStrError(()); + +//--- Display and Error + +impl fmt::Display for SchemeFromStrError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "unknown zonemd scheme mnemonic") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for SchemeFromStrError {} + /// The Hash Algorithm used to construct the digest. /// /// This enumeration wraps an 8-bit unsigned integer that identifies @@ -394,12 +430,42 @@ impl From for Algorithm { } } +impl FromStr for Algorithm { + type Err = AlgorithmFromStrError; + + // Only implement the actionable variants + fn from_str(s: &str) -> Result { + match s { + "1" | "SHA384" => Ok(Self::Sha384), + "2" | "SHA512" => Ok(Self::Sha512), + _ => Err(AlgorithmFromStrError(())), + } + } +} + impl ZonefileFmt for Algorithm { fn fmt(&self, p: &mut impl Formatter) -> zonefile_fmt::Result { p.write_token(u8::from(*self)) } } +//------------ AlgorithmFromStrError --------------------------------------------- + +/// An error occured while reading the algorithm from a string. +#[derive(Clone, Copy, Debug, Eq, PartialEq)] +pub struct AlgorithmFromStrError(()); + +//--- Display and Error + +impl fmt::Display for AlgorithmFromStrError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "unknown zonemd hash algorithm mnemonic") + } +} + +#[cfg(feature = "std")] +impl std::error::Error for AlgorithmFromStrError {} + #[cfg(test)] #[cfg(all(feature = "std", feature = "bytes"))] mod test {