From 145dc2b15feb0518baaba49db7bb23bd436158b8 Mon Sep 17 00:00:00 2001 From: Martin Hoffmann Date: Mon, 5 Feb 2024 10:34:31 +0100 Subject: [PATCH] Introduce ParseAnyRecordData trait. (#256) This PR introduces a new trait ParseAnyRecordData as a companion to ParseRecordData for types that can parse record data of any record type. --- src/base/message.rs | 89 +++++++++++++- src/base/rdata.rs | 57 +++++++-- src/base/record.rs | 75 ++++++++++-- src/rdata/macros.rs | 278 ++++++++++++++++++++++---------------------- 4 files changed, 342 insertions(+), 157 deletions(-) diff --git a/src/base/message.rs b/src/base/message.rs index 79db7997..5ac2a4cc 100644 --- a/src/base/message.rs +++ b/src/base/message.rs @@ -16,7 +16,7 @@ use super::message_builder::{AdditionalBuilder, AnswerBuilder, PushError}; use super::name::ParsedDname; use super::opt::{Opt, OptRecord}; use super::question::Question; -use super::rdata::ParseRecordData; +use super::rdata::{ParseAnyRecordData, ParseRecordData}; use super::record::{ComposeRecord, ParsedRecord, Record}; use super::wire::{Composer, ParseError}; use crate::rdata::rfc1035::Cname; @@ -968,6 +968,14 @@ impl<'a, Octs: Octets + ?Sized> RecordSection<'a, Octs> { RecordIter::new(self, true) } + /// Trades `self` for an interator over all the record. + #[must_use] + pub fn into_records>( + self, + ) -> AnyRecordIter<'a, Octs, Data> { + AnyRecordIter::new(self) + } + /// Proceeds to the next section if there is one. /// /// Returns an error if parsing has failed and the message is unusable @@ -1169,6 +1177,85 @@ where } } +//------------ AnyRecordIter ------------------------------------------------- + +/// An iterator over the records of a record section of a DNS message. +/// +/// The iterator’s item type is the result of trying to parse a record. +/// If parsing the record data fails, the iterator will return an +/// error but can continue with the next record. If parsing the entire record +/// fails the item will be an error and subsequent attempts to continue will +/// also produce errors. This case can be distinguished from an error while +/// parsing the record data by [`next_section`] returning an error, too. +#[derive(Debug)] +pub struct AnyRecordIter<'a, Octs: ?Sized, Data> { + section: RecordSection<'a, Octs>, + marker: PhantomData, +} + +impl<'a, Octs, Data> AnyRecordIter<'a, Octs, Data> +where + Octs: Octets + ?Sized, + Data: ParseAnyRecordData<'a, Octs>, +{ + /// Creates a new record iterator. + fn new(section: RecordSection<'a, Octs>) -> Self { + Self { + section, + marker: PhantomData, + } + } + + /// Trades the limited iterator for the full iterator. + /// + /// The returned iterator will continue right after the last record + /// previously returned. + #[must_use] + pub fn unwrap(self) -> RecordSection<'a, Octs> { + self.section + } + + /// Proceeds to the next section if there is one. + /// + /// Returns an error if parsing the message has failed. Returns + /// `Ok(None)` if this iterator was already on the additional section. + pub fn next_section( + self, + ) -> Result>, ParseError> { + self.section.next_section() + } +} + +//--- Clone + +impl<'a, Octs: ?Sized, Data> Clone for AnyRecordIter<'a, Octs, Data> { + fn clone(&self) -> Self { + Self { + section: self.section, + marker: PhantomData, + } + } +} + +//--- Iterator + +impl<'a, Octs, Data> Iterator for AnyRecordIter<'a, Octs, Data> +where + Octs: Octets + ?Sized, + Data: ParseAnyRecordData<'a, Octs>, +{ + type Item = + Result>, Data>, ParseError>; + + fn next(&mut self) -> Option { + let record = match self.section.next() { + Some(Ok(record)) => record, + Some(Err(err)) => return Some(Err(err)), + None => return None, + }; + Some(record.into_any_record()) + } +} //============ Error Types =================================================== //------------ ShortMessage -------------------------------------------------- diff --git a/src/base/rdata.rs b/src/base/rdata.rs index ecb0a869..60eefa6e 100644 --- a/src/base/rdata.rs +++ b/src/base/rdata.rs @@ -152,15 +152,13 @@ impl<'a, T: ComposeRecordData> ComposeRecordData for &'a T { } } -//------------ ParseRecordData ----------------------------------------------- +//------------ ParseRecordData and ParseAllRecordData ------------------------ /// A record data type that can be parsed from a message. /// -/// When record data types are generic – typically over a domain name type –, -/// they may not in all cases be parseable. They may still represent record -/// data to be used when constructing the message. -/// -/// To reflect this asymmetry, parsing of record data has its own trait. +/// This trait allows a record data type to express whether it is able to +/// parse record data for a specific record type. It is thus implemented by +/// all record data types included in the [`rdata`][crate::rdata] module. pub trait ParseRecordData<'a, Octs: ?Sized>: RecordData + Sized { /// Parses the record data. /// @@ -169,7 +167,7 @@ pub trait ParseRecordData<'a, Octs: ?Sized>: RecordData + Sized { /// `Ok(None)` if it doesn’t. /// /// The `parser` is positioned at the beginning of the record data and is - /// is limited to the length of the data. The method only needs to parse + /// is limited to the length of the data. The function only needs to parse /// as much data as it needs. The caller has to make sure to deal with /// data remaining in the parser. /// @@ -181,6 +179,32 @@ pub trait ParseRecordData<'a, Octs: ?Sized>: RecordData + Sized { ) -> Result, ParseError>; } +/// A record data type that can parse and represent any type of record. +/// +/// While [`ParseRecordData`] allows a type to signal that it doesn’t +/// actually cover a certain record type, this trait is for types that can +/// parse and represent record data of any type. +/// +/// When implementing a type for this trait, keep in mind that some record +/// types – specifically those defined by [RFC 1035][crate::rdata::rfc1035] – +/// can contain compressed domain names. Thus, this trait cannot be +/// implemented by [`UnknownRecordData`] which just takes the raw data +/// uninterpreted. +pub trait ParseAnyRecordData<'a, Octs: ?Sized>: RecordData + Sized { + /// Parses the record data. + /// + /// The record data is for a record of type `rtype`. + /// + /// The `parser` is positioned at the beginning of the record data and is + /// is limited to the length of the data. The function only needs to parse + /// as much data as it needs. The caller has to make sure to deal with + /// data remaining in the parser. + fn parse_any_rdata( + rtype: Rtype, + parser: &mut Parser<'a, Octs>, + ) -> Result; +} + //------------ UnknownRecordData --------------------------------------------- /// A type for parsing any type of record data. @@ -305,6 +329,25 @@ impl UnknownRecordData { Ok(UnknownRecordData { rtype, data }) } + + /// Parses any record type as unknown record data. + /// + /// This is an associated function rather than an impl of + /// [`ParseAnyRecordData`] because some record types must not be parsed + /// as unknown data as they can contain compressed domain names. + pub fn parse_any_rdata<'a, SrcOcts>( + rtype: Rtype, + parser: &mut Parser<'a, SrcOcts>, + ) -> Result + where + SrcOcts: Octets = Octs> + ?Sized + 'a, + { + let rdlen = parser.remaining(); + parser + .parse_octets(rdlen) + .map(|data| Self { rtype, data }) + .map_err(Into::into) + } } //--- OctetsFrom diff --git a/src/base/record.rs b/src/base/record.rs index f0735e73..132ebb5c 100644 --- a/src/base/record.rs +++ b/src/base/record.rs @@ -18,7 +18,9 @@ use super::cmp::CanonicalOrd; use super::iana::{Class, Rtype}; use super::name::{FlattenInto, ParsedDname, ToDname}; -use super::rdata::{ComposeRecordData, ParseRecordData, RecordData}; +use super::rdata::{ + ComposeRecordData, ParseAnyRecordData, ParseRecordData, RecordData, +}; use super::wire::{Compose, Composer, FormError, Parse, ParseError}; use core::cmp::Ordering; use core::time::Duration; @@ -662,9 +664,9 @@ impl RecordHeader<()> { } impl RecordHeader> { - /// Parses the remainder of the record and returns it. + /// Parses the remainder of the record if the record data type supports it. /// - /// The method assumes that the parsers is currently positioned right + /// The method assumes that the parser is currently positioned right /// after the end of the record header. If the record data type `D` /// feels capable of parsing a record with a header of `self`, the /// method will parse the data and return a full `Record`. Otherwise, @@ -687,6 +689,33 @@ impl RecordHeader> { } Ok(res) } + + /// Parses the remainder of the record. + /// + /// The method assumes that the parser is currently positioned right + /// after the end of the record header. + pub fn parse_into_any_record<'a, Src, Data>( + self, + parser: &mut Parser<'a, Src>, + ) -> Result, Data>, ParseError> + where + Src: AsRef<[u8]> + ?Sized, + Data: ParseAnyRecordData<'a, Src>, + { + let mut parser = parser.parse_parser(self.rdlen as usize)?; + let res = Record::new( + self.owner, + self.class, + self.ttl, + Data::parse_any_rdata(self.rtype, &mut parser)?, + ); + if parser.remaining() > 0 { + return Err(ParseError::Form(FormError::new( + "trailing data in option", + ))); + } + Ok(res) + } } impl RecordHeader { @@ -880,7 +909,7 @@ impl<'a, Octs: Octets + ?Sized> ParsedRecord<'a, Octs> { } impl<'a, Octs: Octets + ?Sized> ParsedRecord<'a, Octs> { - /// Creates a real resource record from the parsed record. + /// Creates a real resource record if the record data type supports it. /// /// The method is generic over a type that knows how to parse record /// data via the [`ParseRecordData`] trait. The record data is given to @@ -889,8 +918,6 @@ impl<'a, Octs: Octets + ?Sized> ParsedRecord<'a, Octs> { /// the method returns `Ok(Some(_))`. It returns `Ok(None)` if the trait /// doesn’t know how to parse this particular record type. It returns /// an error if parsing fails. - /// - /// [`ParseRecordData`]: ../rdata/trait.ParseRecordData.html #[allow(clippy::type_complexity)] pub fn to_record( &self, @@ -903,7 +930,23 @@ impl<'a, Octs: Octets + ?Sized> ParsedRecord<'a, Octs> { .parse_into_record(&mut self.data.clone()) } - /// Trades the parsed record for a real resource record. + /// Creates a real resource record. + /// + /// The method is generic over a type that knows how to parse record + /// data via the [`ParseAnyRecordData`] trait. The record data is given to + /// this trait for parsing. + pub fn to_any_record( + &self, + ) -> Result>, Data>, ParseError> + where + Data: ParseAnyRecordData<'a, Octs>, + { + self.header + .deref_owner() + .parse_into_any_record(&mut self.data.clone()) + } + + /// Trades for a real resource record if the record data type supports it. /// /// The method is generic over a type that knows how to parse record /// data via the [`ParseRecordData`] trait. The record data is given to @@ -912,8 +955,6 @@ impl<'a, Octs: Octets + ?Sized> ParsedRecord<'a, Octs> { /// the method returns `Ok(Some(_))`. It returns `Ok(None)` if the trait /// doesn’t know how to parse this particular record type. It returns /// an error if parsing fails. - /// - /// [`ParseRecordData`]: ../rdata/trait.ParseRecordData.html #[allow(clippy::type_complexity)] pub fn into_record( mut self, @@ -923,6 +964,22 @@ impl<'a, Octs: Octets + ?Sized> ParsedRecord<'a, Octs> { { self.header.deref_owner().parse_into_record(&mut self.data) } + + /// Trades for a real resource record. + /// + /// The method is generic over a type that knows how to parse record + /// data via the [`ParseAnyRecordData`] trait. The record data is given to + /// this trait for parsing. #[allow(clippy::type_complexity)] + pub fn into_any_record( + mut self, + ) -> Result>, Data>, ParseError> + where + Data: ParseAnyRecordData<'a, Octs>, + { + self.header + .deref_owner() + .parse_into_any_record(&mut self.data) + } } impl<'a, Octs: Octets + ?Sized> ParsedRecord<'a, Octs> { diff --git a/src/rdata/macros.rs b/src/rdata/macros.rs index 018784b3..d9969a5a 100644 --- a/src/rdata/macros.rs +++ b/src/rdata/macros.rs @@ -30,10 +30,19 @@ macro_rules! rdata_types { pub mod $module; )* - use crate::base::name::{ParsedDname, ToDname}; - use crate::base::wire::Composer; - use crate::base::rdata::ComposeRecordData; - use octseq::octets::OctetsFrom; + use core::{fmt, hash}; + use crate::base::cmp::CanonicalOrd; + use crate::base::iana::Rtype; + use crate::base::name::{FlattenInto, ParsedDname, ToDname}; + use crate::base::opt::Opt; + use crate::base::rdata::{ + ComposeRecordData, ParseAnyRecordData, ParseRecordData, + RecordData, UnknownRecordData, + }; + use crate::base::scan::ScannerError; + use crate::base::wire::{Composer, ParseError}; + use octseq::octets::{Octets, OctetsFrom}; + use octseq::parse::Parser; //------------- ZoneRecordData --------------------------------------- @@ -71,7 +80,7 @@ macro_rules! rdata_types { $( $( $( $mtype($mtype $( < $( $mn ),* > )*), )* )* )* - Unknown($crate::base::rdata::UnknownRecordData), + Unknown(UnknownRecordData), } impl, Name: ToDname> ZoneRecordData { @@ -81,15 +90,12 @@ macro_rules! rdata_types { /// record types, the returned value will be of the /// `ZoneRecordData::Unknown(_)` variant. pub fn scan( - rtype: $crate::base::iana::Rtype, + rtype: Rtype, scanner: &mut S ) -> Result where S: $crate::base::scan::Scanner { - use $crate::base::rdata::UnknownRecordData; - use $crate::base::scan::ScannerError; - if scanner.scan_opt_unknown_marker()? { UnknownRecordData::scan_without_marker( rtype, scanner @@ -98,7 +104,7 @@ macro_rules! rdata_types { else { match rtype { $( $( $( - $crate::base::iana::Rtype::$mtype => { + Rtype::$mtype => { $mtype::scan( scanner ).map(ZoneRecordData::$mtype) @@ -115,17 +121,11 @@ macro_rules! rdata_types { } impl ZoneRecordData { - fn rtype(&self) -> $crate::base::iana::Rtype { - use $crate::base::rdata::RecordData; - + fn rtype(&self) -> Rtype { match *self { $( $( $( ZoneRecordData::$mtype(ref inner) => { inner.rtype() - /* - <$mtype $( < $( $mn ),* > )* - as $crate::base::rdata::RtypeRecordData>::RTYPE - */ } )* )* )* ZoneRecordData::Unknown(ref inner) => inner.rtype(), @@ -135,21 +135,21 @@ macro_rules! rdata_types { //--- OctetsFrom - impl - octseq::octets::OctetsFrom< - ZoneRecordData + impl + OctetsFrom< + ZoneRecordData > - for ZoneRecordData + for ZoneRecordData where - Octets: octseq::octets::OctetsFrom, - Name: octseq::octets::OctetsFrom< - SrcName, Error = Octets::Error + Octs: OctetsFrom, + Name: OctetsFrom< + SrcName, Error = Octs::Error >, { - type Error = Octets::Error; + type Error = Octs::Error; fn try_octets_from( - source: ZoneRecordData + source: ZoneRecordData ) -> Result { match source { $( $( $( @@ -161,7 +161,6 @@ macro_rules! rdata_types { )* )* )* ZoneRecordData::Unknown(inner) => { Ok(ZoneRecordData::Unknown( - $crate::base::rdata:: UnknownRecordData::try_octets_from(inner)? )) } @@ -171,24 +170,21 @@ macro_rules! rdata_types { //--- FlattenInto - impl - crate::base::name::FlattenInto< - ZoneRecordData + impl + FlattenInto< + ZoneRecordData > - for ZoneRecordData + for ZoneRecordData where - TargetOctets: OctetsFrom, - Name: crate::base::name::FlattenInto< - TargetName, - AppendError = TargetOctets::Error, - >, + TargetOcts: OctetsFrom, + Name: FlattenInto, { - type AppendError = TargetOctets::Error; + type AppendError = TargetOcts::Error; fn try_flatten_into( self ) -> Result< - ZoneRecordData, + ZoneRecordData, Self::AppendError > { match self { @@ -201,7 +197,6 @@ macro_rules! rdata_types { )* )* )* ZoneRecordData::Unknown(inner) => { Ok(ZoneRecordData::Unknown( - $crate::base::rdata:: UnknownRecordData::try_octets_from(inner)? )) } @@ -220,9 +215,9 @@ macro_rules! rdata_types { } )* )* )* - impl From<$crate::base::rdata::UnknownRecordData> + impl From> for ZoneRecordData { - fn from(value: $crate::base::rdata::UnknownRecordData) -> Self { + fn from(value: UnknownRecordData) -> Self { ZoneRecordData::Unknown(value) } } @@ -234,7 +229,7 @@ macro_rules! rdata_types { for ZoneRecordData where O: AsRef<[u8]>, OO: AsRef<[u8]>, - N: $crate::base::name::ToDname, NN: $crate::base::name::ToDname, + N: ToDname, NN: ToDname, { fn eq(&self, other: &ZoneRecordData) -> bool { match (self, other) { @@ -259,7 +254,7 @@ macro_rules! rdata_types { } impl Eq for ZoneRecordData - where O: AsRef<[u8]>, N: $crate::base::name::ToDname { } + where O: AsRef<[u8]>, N: ToDname { } //--- PartialOrd, Ord, and CanonicalOrd @@ -268,7 +263,7 @@ macro_rules! rdata_types { for ZoneRecordData where O: AsRef<[u8]>, OO: AsRef<[u8]>, - N: $crate::base::name::ToDname, NN: $crate::base::name::ToDname, + N: ToDname, NN: ToDname, { fn partial_cmp( &self, @@ -296,13 +291,12 @@ macro_rules! rdata_types { } impl - $crate::base::cmp::CanonicalOrd> + CanonicalOrd> for ZoneRecordData where O: AsRef<[u8]>, OO: AsRef<[u8]>, - N: $crate::base::cmp::CanonicalOrd - + $crate::base::name::ToDname, - NN: $crate::base::name::ToDname, + N: CanonicalOrd + ToDname, + NN: ToDname, { fn canonical_cmp( &self, @@ -331,13 +325,13 @@ macro_rules! rdata_types { //--- Hash - impl core::hash::Hash for ZoneRecordData - where O: AsRef<[u8]>, N: core::hash::Hash { - fn hash(&self, state: &mut H) { + impl hash::Hash for ZoneRecordData + where O: AsRef<[u8]>, N: hash::Hash { + fn hash(&self, state: &mut H) { match *self { $( $( $( ZoneRecordData::$mtype(ref inner) => { - $crate::base::iana::Rtype::$mtype.hash(state); + Rtype::$mtype.hash(state); inner.hash(state) } )* )* )* @@ -351,29 +345,29 @@ macro_rules! rdata_types { //--- RecordData, ParseRecordData, and ComposeRecordData - impl $crate::base::rdata::RecordData for ZoneRecordData { - fn rtype(&self) -> $crate::base::iana::Rtype { + impl RecordData for ZoneRecordData { + fn rtype(&self) -> Rtype { ZoneRecordData::rtype(self) } } - impl<'a, Octs: octseq::octets::Octets + ?Sized> - $crate::base::rdata::ParseRecordData<'a, Octs> + impl<'a, Octs: Octets + ?Sized> + ParseRecordData<'a, Octs> for ZoneRecordData, ParsedDname>> { fn parse_rdata( - rtype: $crate::base::iana::Rtype, - parser: &mut octseq::parse::Parser<'a, Octs>, - ) -> Result, $crate::base::wire::ParseError> { + rtype: Rtype, + parser: &mut Parser<'a, Octs>, + ) -> Result, ParseError> { match rtype { $( $( $( - $crate::base::iana::Rtype::$mtype => { + Rtype::$mtype => { Ok(Some(ZoneRecordData::$mtype( $mtype::parse(parser)? ))) } )* )* )* _ => { - Ok($crate::base::rdata::UnknownRecordData::parse_rdata( + Ok(UnknownRecordData::parse_rdata( rtype, parser )?.map(ZoneRecordData::Unknown)) } @@ -430,13 +424,12 @@ macro_rules! rdata_types { //--- Display - impl core::fmt::Display for ZoneRecordData + impl fmt::Display for ZoneRecordData where O: AsRef<[u8]>, - N: core::fmt::Display + N: fmt::Display { - fn fmt(&self, f: &mut core::fmt::Formatter) - -> core::fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { $( $( $( ZoneRecordData::$mtype(ref inner) => { @@ -450,13 +443,12 @@ macro_rules! rdata_types { //--- Debug - impl core::fmt::Debug for ZoneRecordData + impl fmt::Debug for ZoneRecordData where O: AsRef<[u8]>, - N: core ::fmt::Debug + N: fmt::Debug { - fn fmt(&self, f: &mut core::fmt::Formatter) - -> core::fmt::Result { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match *self { $( $( $( ZoneRecordData::$mtype(ref inner) => { @@ -495,14 +487,12 @@ macro_rules! rdata_types { $( $( $( $ptype($ptype $( < $( $pn ),* > )*), )* )* )* - Opt($crate::base::opt::Opt), - Unknown($crate::base::rdata::UnknownRecordData), + Opt(Opt), + Unknown(UnknownRecordData), } impl AllRecordData { - fn rtype(&self) -> $crate::base::iana::Rtype { - use $crate::base::rdata::RecordData; - + fn rtype(&self) -> Rtype { match *self { $( $( $( AllRecordData::$mtype(ref inner) => { @@ -515,7 +505,7 @@ macro_rules! rdata_types { } )* )* )* - AllRecordData::Opt(_) => $crate::base::iana::Rtype::Opt, + AllRecordData::Opt(_) => Rtype::Opt, AllRecordData::Unknown(ref inner) => inner.rtype(), } } @@ -541,16 +531,16 @@ macro_rules! rdata_types { } )* )* )* - impl From<$crate::base::opt::Opt> for AllRecordData { - fn from(value: $crate::base::opt::Opt) -> Self { + impl From> for AllRecordData { + fn from(value: Opt) -> Self { AllRecordData::Opt(value) } } - impl From<$crate::base::rdata::UnknownRecordData> + impl From> for AllRecordData { fn from( - value: $crate::base::rdata::UnknownRecordData + value: UnknownRecordData ) -> Self { AllRecordData::Unknown(value) } @@ -577,21 +567,21 @@ macro_rules! rdata_types { //--- OctetsFrom - impl - octseq::octets::OctetsFrom< - AllRecordData + impl + OctetsFrom< + AllRecordData > - for AllRecordData + for AllRecordData where - Octets: octseq::octets::OctetsFrom, + Octs: octseq::octets::OctetsFrom, Name: octseq::octets::OctetsFrom< - SrcName, Error = Octets::Error, + SrcName, Error = Octs::Error, >, { - type Error = Octets::Error; + type Error = Octs::Error; fn try_octets_from( - source: AllRecordData + source: AllRecordData ) -> Result { match source { $( $( $( @@ -610,13 +600,12 @@ macro_rules! rdata_types { )* )* )* AllRecordData::Opt(inner) => { Ok(AllRecordData::Opt( - $crate::base::opt::Opt::try_octets_from(inner)? + Opt::try_octets_from(inner)? )) } AllRecordData::Unknown(inner) => { Ok(AllRecordData::Unknown( - $crate::base::rdata::UnknownRecordData - ::try_octets_from(inner)? + UnknownRecordData::try_octets_from(inner)? )) } } @@ -625,24 +614,21 @@ macro_rules! rdata_types { //--- FlattenInto - impl - crate::base::name::FlattenInto< - AllRecordData + impl + FlattenInto< + AllRecordData > - for AllRecordData + for AllRecordData where - TargetOctets: OctetsFrom, - Name: crate::base::name::FlattenInto< - TargetName, - AppendError = TargetOctets::Error, - >, + TargetOcts: OctetsFrom, + Name: FlattenInto, { - type AppendError = TargetOctets::Error; + type AppendError = TargetOcts::Error; fn try_flatten_into( self ) -> Result< - AllRecordData, + AllRecordData, Self::AppendError > { match self { @@ -662,12 +648,11 @@ macro_rules! rdata_types { )* )* )* AllRecordData::Opt(inner) => { Ok(AllRecordData::Opt( - $crate::base::opt::Opt::try_octets_from(inner)? + Opt::try_octets_from(inner)? )) } AllRecordData::Unknown(inner) => { Ok(AllRecordData::Unknown( - $crate::base::rdata:: UnknownRecordData::try_octets_from(inner)? )) } @@ -682,7 +667,7 @@ macro_rules! rdata_types { for AllRecordData where O: AsRef<[u8]>, OO: AsRef<[u8]>, - N: $crate::base::name::ToDname, NN: $crate::base::name::ToDname + N: ToDname, NN: ToDname { fn eq(&self, other: &AllRecordData) -> bool { match (self, other) { @@ -708,14 +693,14 @@ macro_rules! rdata_types { } impl Eq for AllRecordData - where O: AsRef<[u8]>, N: $crate::base::name::ToDname { } + where O: AsRef<[u8]>, N: ToDname { } //--- Hash - impl core::hash::Hash for AllRecordData - where O: AsRef<[u8]>, N: core::hash::Hash { - fn hash(&self, state: &mut H) { + impl hash::Hash for AllRecordData + where O: AsRef<[u8]>, N: hash::Hash { + fn hash(&self, state: &mut H) { self.rtype().hash(state); match *self { $( $( $( @@ -740,8 +725,8 @@ macro_rules! rdata_types { //--- RecordData and ParseRecordData - impl $crate::base::rdata::RecordData for AllRecordData { - fn rtype(&self) -> $crate::base::iana::Rtype { + impl RecordData for AllRecordData { + fn rtype(&self) -> Rtype { match *self { $( $( $( AllRecordData::$mtype(ref inner) => { @@ -759,42 +744,55 @@ macro_rules! rdata_types { } } - impl<'a, Octs: octseq::octets::Octets> - $crate::base::rdata::ParseRecordData<'a, Octs> + impl<'a, Octs: Octets> + ParseAnyRecordData<'a, Octs> for AllRecordData, ParsedDname>> { - fn parse_rdata( - rtype: $crate::base::iana::Rtype, - parser: &mut octseq::parse::Parser<'a, Octs>, - ) -> Result, crate::base::wire::ParseError> { + fn parse_any_rdata( + rtype: Rtype, + parser: &mut Parser<'a, Octs>, + ) -> Result { match rtype { $( $( $( - $crate::base::iana::Rtype::$mtype => { - Ok(Some(AllRecordData::$mtype( + Rtype::$mtype => { + Ok(AllRecordData::$mtype( $mtype::parse(parser)? - ))) + )) } )* )* )* $( $( $( - $crate::base::iana::Rtype::$ptype => { - Ok(Some(AllRecordData::$ptype( + Rtype::$ptype => { + Ok(AllRecordData::$ptype( $ptype::parse(parser)? - ))) + )) } )* )* )* $crate::base::iana::Rtype::Opt => { - Ok(Some(AllRecordData::Opt( - $crate::base::opt::Opt::parse(parser)? - ))) + Ok(AllRecordData::Opt( + Opt::parse(parser)? + )) } _ => { - Ok($crate::base::rdata::UnknownRecordData::parse_rdata( - rtype, parser - )?.map(AllRecordData::Unknown)) + Ok(AllRecordData::Unknown( + UnknownRecordData::parse_any_rdata( + rtype, parser + )? + )) } } } } + impl<'a, Octs: Octets> + ParseRecordData<'a, Octs> + for AllRecordData, ParsedDname>> { + fn parse_rdata( + rtype: Rtype, + parser: &mut Parser<'a, Octs>, + ) -> Result, ParseError> { + ParseAnyRecordData::parse_any_rdata(rtype, parser).map(Some) + } + } + impl ComposeRecordData for AllRecordData where Octs: AsRef<[u8]>, Name: ToDname { fn rdlen(&self, compress: bool) -> Option { @@ -868,11 +866,11 @@ macro_rules! rdata_types { //--- Display and Debug - impl core::fmt::Display for AllRecordData - where O: octseq::octets::Octets, N: core::fmt::Display { + impl fmt::Display for AllRecordData + where O: Octets, N: fmt::Display { fn fmt( - &self, f: &mut core::fmt::Formatter - ) -> core::fmt::Result { + &self, f: &mut fmt::Formatter + ) -> fmt::Result { match *self { $( $( $( AllRecordData::$mtype(ref inner) => { @@ -890,11 +888,11 @@ macro_rules! rdata_types { } } - impl core::fmt::Debug for AllRecordData - where O: octseq::octets::Octets, N: core::fmt::Debug { + impl fmt::Debug for AllRecordData + where O: Octets, N: fmt::Debug { fn fmt( - &self, f: &mut core::fmt::Formatter - ) -> core::fmt::Result { + &self, f: &mut fmt::Formatter + ) -> fmt::Result { match *self { $( $( $( AllRecordData::$mtype(ref inner) => { @@ -905,7 +903,7 @@ macro_rules! rdata_types { "(" ) )?; - core::fmt::Debug::fmt(inner, f)?; + fmt::Debug::fmt(inner, f)?; f.write_str(")") } )* )* )* @@ -918,18 +916,18 @@ macro_rules! rdata_types { "(" ) )?; - core::fmt::Debug::fmt(inner, f)?; + fmt::Debug::fmt(inner, f)?; f.write_str(")") } )* )* )* AllRecordData::Opt(ref inner) => { f.write_str("AllRecordData::Opt(")?; - core::fmt::Debug::fmt(inner, f)?; + fmt::Debug::fmt(inner, f)?; f.write_str(")") } AllRecordData::Unknown(ref inner) => { f.write_str("AllRecordData::Unknown(")?; - core::fmt::Debug::fmt(inner, f)?; + fmt::Debug::fmt(inner, f)?; f.write_str(")") } }