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.
This commit is contained in:
Martin Hoffmann
2024-02-05 10:34:31 +01:00
committed by GitHub
parent db012e4ad9
commit 145dc2b15f
4 changed files with 342 additions and 157 deletions
+88 -1
View File
@@ -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<Data: ParseAnyRecordData<'a, Octs>>(
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<Data>,
}
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<Option<RecordSection<'a, Octs>>, 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<Record<ParsedDname<Octs::Range<'a>>, Data>, ParseError>;
fn next(&mut self) -> Option<Self::Item> {
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 --------------------------------------------------
+50 -7
View File
@@ -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<Option<Self>, 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<Self, ParseError>;
}
//------------ UnknownRecordData ---------------------------------------------
/// A type for parsing any type of record data.
@@ -305,6 +329,25 @@ impl<Octs> UnknownRecordData<Octs> {
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<Self, ParseError>
where
SrcOcts: Octets<Range<'a> = Octs> + ?Sized + 'a,
{
let rdlen = parser.remaining();
parser
.parse_octets(rdlen)
.map(|data| Self { rtype, data })
.map_err(Into::into)
}
}
//--- OctetsFrom
+66 -9
View File
@@ -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<Octs> RecordHeader<ParsedDname<Octs>> {
/// 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<D>`. Otherwise,
@@ -687,6 +689,33 @@ impl<Octs> RecordHeader<ParsedDname<Octs>> {
}
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<Record<ParsedDname<Octs>, 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<Name: ToDname> RecordHeader<Name> {
@@ -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<Data>(
&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<Data>(
&self,
) -> Result<Record<ParsedDname<Octs::Range<'_>>, 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<Data>(
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<Data>(
mut self,
) -> Result<Record<ParsedDname<Octs::Range<'a>>, 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> {
+138 -140
View File
@@ -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<O>),
Unknown(UnknownRecordData<O>),
}
impl<Octets: AsRef<[u8]>, Name: ToDname> ZoneRecordData<Octets, Name> {
@@ -81,15 +90,12 @@ macro_rules! rdata_types {
/// record types, the returned value will be of the
/// `ZoneRecordData::Unknown(_)` variant.
pub fn scan<S>(
rtype: $crate::base::iana::Rtype,
rtype: Rtype,
scanner: &mut S
) -> Result<Self, S::Error>
where
S: $crate::base::scan::Scanner<Octets = Octets, Dname = Name>
{
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<O, N> ZoneRecordData<O, N> {
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<Octets, SrcOctets, Name, SrcName>
octseq::octets::OctetsFrom<
ZoneRecordData<SrcOctets, SrcName>
impl<Octs, SrcOcts, Name, SrcName>
OctetsFrom<
ZoneRecordData<SrcOcts, SrcName>
>
for ZoneRecordData<Octets, Name>
for ZoneRecordData<Octs, Name>
where
Octets: octseq::octets::OctetsFrom<SrcOctets>,
Name: octseq::octets::OctetsFrom<
SrcName, Error = Octets::Error
Octs: OctetsFrom<SrcOcts>,
Name: OctetsFrom<
SrcName, Error = Octs::Error
>,
{
type Error = Octets::Error;
type Error = Octs::Error;
fn try_octets_from(
source: ZoneRecordData<SrcOctets, SrcName>
source: ZoneRecordData<SrcOcts, SrcName>
) -> Result<Self, Self::Error> {
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<Octets, TargetOctets, Name, TargetName>
crate::base::name::FlattenInto<
ZoneRecordData<TargetOctets, TargetName>
impl<Octs, TargetOcts, Name, TargetName>
FlattenInto<
ZoneRecordData<TargetOcts, TargetName>
>
for ZoneRecordData<Octets, Name>
for ZoneRecordData<Octs, Name>
where
TargetOctets: OctetsFrom<Octets>,
Name: crate::base::name::FlattenInto<
TargetName,
AppendError = TargetOctets::Error,
>,
TargetOcts: OctetsFrom<Octs>,
Name: FlattenInto<TargetName, AppendError = TargetOcts::Error>,
{
type AppendError = TargetOctets::Error;
type AppendError = TargetOcts::Error;
fn try_flatten_into(
self
) -> Result<
ZoneRecordData<TargetOctets, TargetName>,
ZoneRecordData<TargetOcts, TargetName>,
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<O, N> From<$crate::base::rdata::UnknownRecordData<O>>
impl<O, N> From<UnknownRecordData<O>>
for ZoneRecordData<O, N> {
fn from(value: $crate::base::rdata::UnknownRecordData<O>) -> Self {
fn from(value: UnknownRecordData<O>) -> Self {
ZoneRecordData::Unknown(value)
}
}
@@ -234,7 +229,7 @@ macro_rules! rdata_types {
for ZoneRecordData<O, N>
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<OO, NN>) -> bool {
match (self, other) {
@@ -259,7 +254,7 @@ macro_rules! rdata_types {
}
impl<O, N> Eq for ZoneRecordData<O, N>
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<O, N>
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<O, OO, N, NN>
$crate::base::cmp::CanonicalOrd<ZoneRecordData<OO, NN>>
CanonicalOrd<ZoneRecordData<OO, NN>>
for ZoneRecordData<O, N>
where
O: AsRef<[u8]>, OO: AsRef<[u8]>,
N: $crate::base::cmp::CanonicalOrd<NN>
+ $crate::base::name::ToDname,
NN: $crate::base::name::ToDname,
N: CanonicalOrd<NN> + ToDname,
NN: ToDname,
{
fn canonical_cmp(
&self,
@@ -331,13 +325,13 @@ macro_rules! rdata_types {
//--- Hash
impl<O, N> core::hash::Hash for ZoneRecordData<O, N>
where O: AsRef<[u8]>, N: core::hash::Hash {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
impl<O, N> hash::Hash for ZoneRecordData<O, N>
where O: AsRef<[u8]>, N: hash::Hash {
fn hash<H: hash::Hasher>(&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<O, N> $crate::base::rdata::RecordData for ZoneRecordData<O, N> {
fn rtype(&self) -> $crate::base::iana::Rtype {
impl<O, N> RecordData for ZoneRecordData<O, N> {
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<Octs::Range<'a>, ParsedDname<Octs::Range<'a>>> {
fn parse_rdata(
rtype: $crate::base::iana::Rtype,
parser: &mut octseq::parse::Parser<'a, Octs>,
) -> Result<Option<Self>, $crate::base::wire::ParseError> {
rtype: Rtype,
parser: &mut Parser<'a, Octs>,
) -> Result<Option<Self>, 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<O, N> core::fmt::Display for ZoneRecordData<O, N>
impl<O, N> fmt::Display for ZoneRecordData<O, N>
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<O, N> core::fmt::Debug for ZoneRecordData<O, N>
impl<O, N> fmt::Debug for ZoneRecordData<O, N>
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<O>),
Unknown($crate::base::rdata::UnknownRecordData<O>),
Opt(Opt<O>),
Unknown(UnknownRecordData<O>),
}
impl<O, N> AllRecordData<O, N> {
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<O, N> From<$crate::base::opt::Opt<O>> for AllRecordData<O, N> {
fn from(value: $crate::base::opt::Opt<O>) -> Self {
impl<O, N> From<Opt<O>> for AllRecordData<O, N> {
fn from(value: Opt<O>) -> Self {
AllRecordData::Opt(value)
}
}
impl<O, N> From<$crate::base::rdata::UnknownRecordData<O>>
impl<O, N> From<UnknownRecordData<O>>
for AllRecordData<O, N> {
fn from(
value: $crate::base::rdata::UnknownRecordData<O>
value: UnknownRecordData<O>
) -> Self {
AllRecordData::Unknown(value)
}
@@ -577,21 +567,21 @@ macro_rules! rdata_types {
//--- OctetsFrom
impl<Octets, SrcOctets, Name, SrcName>
octseq::octets::OctetsFrom<
AllRecordData<SrcOctets, SrcName>
impl<Octs, SrcOcts, Name, SrcName>
OctetsFrom<
AllRecordData<SrcOcts, SrcName>
>
for AllRecordData<Octets, Name>
for AllRecordData<Octs, Name>
where
Octets: octseq::octets::OctetsFrom<SrcOctets>,
Octs: octseq::octets::OctetsFrom<SrcOcts>,
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<SrcOctets, SrcName>
source: AllRecordData<SrcOcts, SrcName>
) -> Result<Self, Self::Error> {
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<Octets, TargetOctets, Name, TargetName>
crate::base::name::FlattenInto<
AllRecordData<TargetOctets, TargetName>
impl<Octs, TargetOcts, Name, TargetName>
FlattenInto<
AllRecordData<TargetOcts, TargetName>
>
for AllRecordData<Octets, Name>
for AllRecordData<Octs, Name>
where
TargetOctets: OctetsFrom<Octets>,
Name: crate::base::name::FlattenInto<
TargetName,
AppendError = TargetOctets::Error,
>,
TargetOcts: OctetsFrom<Octs>,
Name: FlattenInto<TargetName, AppendError = TargetOcts::Error>,
{
type AppendError = TargetOctets::Error;
type AppendError = TargetOcts::Error;
fn try_flatten_into(
self
) -> Result<
AllRecordData<TargetOctets, TargetName>,
AllRecordData<TargetOcts, TargetName>,
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<O, N>
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<OO, NN>) -> bool {
match (self, other) {
@@ -708,14 +693,14 @@ macro_rules! rdata_types {
}
impl<O, N> Eq for AllRecordData<O, N>
where O: AsRef<[u8]>, N: $crate::base::name::ToDname { }
where O: AsRef<[u8]>, N: ToDname { }
//--- Hash
impl<O, N> core::hash::Hash for AllRecordData<O, N>
where O: AsRef<[u8]>, N: core::hash::Hash {
fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
impl<O, N> hash::Hash for AllRecordData<O, N>
where O: AsRef<[u8]>, N: hash::Hash {
fn hash<H: hash::Hasher>(&self, state: &mut H) {
self.rtype().hash(state);
match *self {
$( $( $(
@@ -740,8 +725,8 @@ macro_rules! rdata_types {
//--- RecordData and ParseRecordData
impl<O, N> $crate::base::rdata::RecordData for AllRecordData<O, N> {
fn rtype(&self) -> $crate::base::iana::Rtype {
impl<O, N> RecordData for AllRecordData<O, N> {
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<Octs::Range<'a>, ParsedDname<Octs::Range<'a>>> {
fn parse_rdata(
rtype: $crate::base::iana::Rtype,
parser: &mut octseq::parse::Parser<'a, Octs>,
) -> Result<Option<Self>, crate::base::wire::ParseError> {
fn parse_any_rdata(
rtype: Rtype,
parser: &mut Parser<'a, Octs>,
) -> Result<Self, ParseError> {
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<Octs::Range<'a>, ParsedDname<Octs::Range<'a>>> {
fn parse_rdata(
rtype: Rtype,
parser: &mut Parser<'a, Octs>,
) -> Result<Option<Self>, ParseError> {
ParseAnyRecordData::parse_any_rdata(rtype, parser).map(Some)
}
}
impl<Octs, Name> ComposeRecordData for AllRecordData<Octs, Name>
where Octs: AsRef<[u8]>, Name: ToDname {
fn rdlen(&self, compress: bool) -> Option<u16> {
@@ -868,11 +866,11 @@ macro_rules! rdata_types {
//--- Display and Debug
impl<O, N> core::fmt::Display for AllRecordData<O, N>
where O: octseq::octets::Octets, N: core::fmt::Display {
impl<O, N> fmt::Display for AllRecordData<O, N>
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<O, N> core::fmt::Debug for AllRecordData<O, N>
where O: octseq::octets::Octets, N: core::fmt::Debug {
impl<O, N> fmt::Debug for AllRecordData<O, N>
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(")")
}
}