domain/rdata/
macros.rs

1//! Macros for use in rdata definitions.
2//!
3//! These macros are not public but are used by the super module only. They
4//! are here so that `mod.rs` doesn’t become too unwieldly.
5
6macro_rules! rdata_types {
7    ( $(
8        $module:ident::{
9            $(
10                zone {
11                    $( $mtype:ident $( < $( $mn:ident ),* > ),* $(,)? )*
12                }
13            )*
14            $(
15                pseudo {
16                    $( $ptype:ident $( < $( $pn:ident ),* > ),*  $(,)? )*
17                }
18            )*
19
20        }
21    )* ) => {
22        $(
23            pub use self::$module::{
24                $( $( $mtype, )* )*
25                $( $( $ptype ),* )*
26            };
27        )*
28
29        $(
30            pub mod $module;
31        )*
32
33        use crate::base::name::{ParsedDname, ToDname};
34        use crate::base::wire::Composer;
35        use crate::base::rdata::ComposeRecordData;
36        use octseq::octets::OctetsFrom;
37
38
39        //------------- ZoneRecordData ---------------------------------------
40
41        /// Record data for all record types allowed in zone files.
42        ///
43        /// This enum collects the record data types for all currently
44        /// implemented record types that are allowed to be included in zone
45        /// files.
46        #[derive(Clone)]
47        #[cfg_attr(
48            feature = "serde",
49            derive(serde::Serialize, serde::Deserialize)
50        )]
51        #[cfg_attr(
52            feature = "serde",
53            serde(bound(
54                serialize = "
55                    O: AsRef<[u8]> + octseq::serde::SerializeOctets,
56                    N: serde::Serialize,
57                ",
58                deserialize = "
59                    O: octseq::builder::FromBuilder
60                        + octseq::serde::DeserializeOctets<'de>,
61                    <O as octseq::builder::FromBuilder>::Builder:
62                          octseq::builder::EmptyBuilder
63                        + octseq::builder::Truncate
64                        + AsRef<[u8]> + AsMut<[u8]>,
65                    N: serde::Deserialize<'de>,
66                ",
67            ))
68        )]
69        #[non_exhaustive]
70        pub enum ZoneRecordData<O, N> {
71            $( $( $(
72                $mtype($mtype $( < $( $mn ),* > )*),
73            )* )* )*
74            Unknown($crate::base::rdata::UnknownRecordData<O>),
75        }
76
77        impl<Octets: AsRef<[u8]>, Name: ToDname> ZoneRecordData<Octets, Name> {
78            /// Scans a value of the given rtype.
79            ///
80            /// If the record data is given via the notation for unknown
81            /// record types, the returned value will be of the
82            /// `ZoneRecordData::Unknown(_)` variant.
83            pub fn scan<S>(
84                rtype: $crate::base::iana::Rtype,
85                scanner: &mut S
86            ) -> Result<Self, S::Error>
87            where
88                S: $crate::base::scan::Scanner<Octets = Octets, Dname = Name>
89            {
90                use $crate::base::rdata::UnknownRecordData;
91                use $crate::base::scan::ScannerError;
92
93                if scanner.scan_opt_unknown_marker()? {
94                    UnknownRecordData::scan_without_marker(
95                        rtype, scanner
96                    ).map(ZoneRecordData::Unknown)
97                }
98                else {
99                    match rtype {
100                        $( $( $(
101                            $crate::base::iana::Rtype::$mtype => {
102                                $mtype::scan(
103                                    scanner
104                                ).map(ZoneRecordData::$mtype)
105                            }
106                        )* )* )*
107                        _ => {
108                            Err(S::Error::custom(
109                                "unknown record type with concrete data"
110                            ))
111                        }
112                    }
113                }
114            }
115        }
116
117        impl<O, N> ZoneRecordData<O, N> {
118            fn rtype(&self) -> $crate::base::iana::Rtype {
119                use $crate::base::rdata::RecordData;
120
121                match *self {
122                    $( $( $(
123                        ZoneRecordData::$mtype(ref inner) => {
124                            inner.rtype()
125                            /*
126                            <$mtype $( < $( $mn ),* > )*
127                                as $crate::base::rdata::RtypeRecordData>::RTYPE
128                            */
129                        }
130                    )* )* )*
131                    ZoneRecordData::Unknown(ref inner) => inner.rtype(),
132                }
133            }
134        }
135
136        //--- OctetsFrom
137
138        impl<Octets, SrcOctets, Name, SrcName>
139            octseq::octets::OctetsFrom<
140                ZoneRecordData<SrcOctets, SrcName>
141            >
142            for ZoneRecordData<Octets, Name>
143        where
144            Octets: octseq::octets::OctetsFrom<SrcOctets>,
145            Name: octseq::octets::OctetsFrom<
146                SrcName, Error = Octets::Error
147            >,
148        {
149            type Error = Octets::Error;
150
151            fn try_octets_from(
152                source: ZoneRecordData<SrcOctets, SrcName>
153            ) -> Result<Self, Self::Error> {
154                match source {
155                    $( $( $(
156                        ZoneRecordData::$mtype(inner) => {
157                            inner.convert_octets().map(
158                                ZoneRecordData::$mtype
159                            )
160                        }
161                    )* )* )*
162                    ZoneRecordData::Unknown(inner) => {
163                        Ok(ZoneRecordData::Unknown(
164                            $crate::base::rdata::
165                            UnknownRecordData::try_octets_from(inner)?
166                        ))
167                    }
168                }
169            }
170        }
171
172        //--- FlattenInto
173
174        impl<Octets, TargetOctets, Name, TargetName>
175            crate::base::name::FlattenInto<
176                ZoneRecordData<TargetOctets, TargetName>
177            >
178            for ZoneRecordData<Octets, Name>
179        where
180            TargetOctets: OctetsFrom<Octets>,
181            Name: crate::base::name::FlattenInto<
182                TargetName,
183                AppendError = TargetOctets::Error,
184            >,
185        {
186            type AppendError = TargetOctets::Error;
187
188            fn try_flatten_into(
189                self
190            ) -> Result<
191                ZoneRecordData<TargetOctets, TargetName>,
192                Self::AppendError
193            > {
194                match self {
195                    $( $( $(
196                        ZoneRecordData::$mtype(inner) => {
197                            inner.flatten().map(
198                                ZoneRecordData::$mtype
199                            )
200                        }
201                    )* )* )*
202                    ZoneRecordData::Unknown(inner) => {
203                        Ok(ZoneRecordData::Unknown(
204                            $crate::base::rdata::
205                            UnknownRecordData::try_octets_from(inner)?
206                        ))
207                    }
208                }
209            }
210        }
211
212        //--- From
213
214        $( $( $(
215            impl<O, N> From<$mtype $( < $( $mn ),* >)*>
216            for ZoneRecordData<O, N> {
217                fn from(value: $mtype $( < $( $mn ),* >)*) -> Self {
218                    ZoneRecordData::$mtype(value)
219                }
220            }
221        )* )* )*
222
223        impl<O, N> From<$crate::base::rdata::UnknownRecordData<O>>
224        for ZoneRecordData<O, N> {
225            fn from(value: $crate::base::rdata::UnknownRecordData<O>) -> Self {
226                ZoneRecordData::Unknown(value)
227            }
228        }
229
230
231        //--- PartialEq and Eq
232
233        impl<O, OO, N, NN> PartialEq<ZoneRecordData<OO, NN>>
234        for ZoneRecordData<O, N>
235        where
236            O: AsRef<[u8]>, OO: AsRef<[u8]>,
237            N: $crate::base::name::ToDname, NN: $crate::base::name::ToDname,
238        {
239            fn eq(&self, other: &ZoneRecordData<OO, NN>) -> bool {
240                match (self, other) {
241                    $( $( $(
242                        (
243                            &ZoneRecordData::$mtype(ref self_inner),
244                            &ZoneRecordData::$mtype(ref other_inner)
245                        )
246                        => {
247                            self_inner.eq(other_inner)
248                        }
249                    )* )* )*
250                    (
251                        &ZoneRecordData::Unknown(ref self_inner),
252                        &ZoneRecordData::Unknown(ref other_inner)
253                    ) => {
254                        self_inner.eq(other_inner)
255                    }
256                    _ => false
257                }
258            }
259        }
260
261        impl<O, N> Eq for ZoneRecordData<O, N>
262        where O: AsRef<[u8]>, N: $crate::base::name::ToDname { }
263
264
265        //--- PartialOrd, Ord, and CanonicalOrd
266
267        impl<O, OO, N, NN> PartialOrd<ZoneRecordData<OO, NN>>
268        for ZoneRecordData<O, N>
269        where
270            O: AsRef<[u8]>, OO: AsRef<[u8]>,
271            N: $crate::base::name::ToDname, NN: $crate::base::name::ToDname,
272        {
273            fn partial_cmp(
274                &self,
275                other: &ZoneRecordData<OO, NN>
276            ) -> Option<core::cmp::Ordering> {
277                match (self, other) {
278                    $( $( $(
279                        (
280                            &ZoneRecordData::$mtype(ref self_inner),
281                            &ZoneRecordData::$mtype(ref other_inner)
282                        )
283                        => {
284                            self_inner.partial_cmp(other_inner)
285                        }
286                    )* )* )*
287                    (
288                        &ZoneRecordData::Unknown(ref self_inner),
289                        &ZoneRecordData::Unknown(ref other_inner)
290                    ) => {
291                        self_inner.partial_cmp(other_inner)
292                    }
293                    _ => self.rtype().partial_cmp(&other.rtype())
294                }
295            }
296        }
297
298        impl<O, OO, N, NN>
299        $crate::base::cmp::CanonicalOrd<ZoneRecordData<OO, NN>>
300        for ZoneRecordData<O, N>
301        where
302            O: AsRef<[u8]>, OO: AsRef<[u8]>,
303            N: $crate::base::cmp::CanonicalOrd<NN>
304                + $crate::base::name::ToDname,
305            NN: $crate::base::name::ToDname,
306        {
307            fn canonical_cmp(
308                &self,
309                other: &ZoneRecordData<OO, NN>
310            ) -> core::cmp::Ordering {
311                match (self, other) {
312                    $( $( $(
313                        (
314                            &ZoneRecordData::$mtype(ref self_inner),
315                            &ZoneRecordData::$mtype(ref other_inner)
316                        )
317                        => {
318                            self_inner.canonical_cmp(other_inner)
319                        }
320                    )* )* )*
321                    (
322                        &ZoneRecordData::Unknown(ref self_inner),
323                        &ZoneRecordData::Unknown(ref other_inner)
324                    ) => {
325                        self_inner.canonical_cmp(other_inner)
326                    }
327                    _ => self.rtype().cmp(&other.rtype())
328                }
329            }
330        }
331
332        //--- Hash
333
334        impl<O, N> core::hash::Hash for ZoneRecordData<O, N>
335        where O: AsRef<[u8]>, N: core::hash::Hash {
336            fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
337                match *self {
338                    $( $( $(
339                        ZoneRecordData::$mtype(ref inner) => {
340                            $crate::base::iana::Rtype::$mtype.hash(state);
341                            inner.hash(state)
342                        }
343                    )* )* )*
344                    ZoneRecordData::Unknown(ref inner) => {
345                        inner.rtype().hash(state);
346                        inner.data().as_ref().hash(state);
347                    }
348                }
349            }
350        }
351
352        //--- RecordData, ParseRecordData, and ComposeRecordData
353
354        impl<O, N> $crate::base::rdata::RecordData for ZoneRecordData<O, N> {
355            fn rtype(&self) -> $crate::base::iana::Rtype {
356                ZoneRecordData::rtype(self)
357            }
358        }
359
360        impl<'a, Octs: octseq::octets::Octets + ?Sized>
361        $crate::base::rdata::ParseRecordData<'a, Octs>
362        for ZoneRecordData<Octs::Range<'a>, ParsedDname<Octs::Range<'a>>> {
363            fn parse_rdata(
364                rtype: $crate::base::iana::Rtype,
365                parser: &mut octseq::parse::Parser<'a, Octs>,
366            ) -> Result<Option<Self>, $crate::base::wire::ParseError> {
367                match rtype {
368                    $( $( $(
369                        $crate::base::iana::Rtype::$mtype => {
370                            Ok(Some(ZoneRecordData::$mtype(
371                                $mtype::parse(parser)?
372                            )))
373                        }
374                    )* )* )*
375                    _ => {
376                        Ok($crate::base::rdata::UnknownRecordData::parse_rdata(
377                            rtype, parser
378                        )?.map(ZoneRecordData::Unknown))
379                    }
380                }
381            }
382        }
383
384        impl<Octs, Name> ComposeRecordData for ZoneRecordData<Octs, Name>
385        where Octs: AsRef<[u8]>, Name: ToDname {
386            fn rdlen(&self, compress: bool) -> Option<u16> {
387                match *self {
388                    $( $( $(
389                        ZoneRecordData::$mtype(ref inner) => {
390                            inner.rdlen(compress)
391                        }
392                    )* )* )*
393                    ZoneRecordData::Unknown(ref inner) => {
394                        inner.rdlen(compress)
395                    }
396                }
397            }
398
399            fn compose_rdata<Target: Composer + ?Sized>(
400                &self, target: &mut Target
401            ) -> Result<(), Target::AppendError> {
402                match *self {
403                    $( $( $(
404                        ZoneRecordData::$mtype(ref inner) => {
405                            inner.compose_rdata(target)
406                        }
407                    )* )* )*
408                    ZoneRecordData::Unknown(ref inner) => {
409                        inner.compose_rdata(target)
410                    }
411                }
412            }
413
414            fn compose_canonical_rdata<Target: Composer + ?Sized>(
415                &self, target: &mut Target
416            ) -> Result<(), Target::AppendError> {
417                match *self {
418                    $( $( $(
419                        ZoneRecordData::$mtype(ref inner) => {
420                            inner.compose_canonical_rdata(target)
421                        }
422                    )* )* )*
423                    ZoneRecordData::Unknown(ref inner) => {
424                        inner.compose_canonical_rdata(target)
425                    }
426                }
427            }
428        }
429
430
431        //--- Display
432
433        impl<O, N> core::fmt::Display for ZoneRecordData<O, N>
434        where
435            O: AsRef<[u8]>,
436            N: core::fmt::Display
437        {
438            fn fmt(&self, f: &mut core::fmt::Formatter)
439                   -> core::fmt::Result {
440                match *self {
441                    $( $( $(
442                        ZoneRecordData::$mtype(ref inner) => {
443                            inner.fmt(f)
444                        }
445                    )* )* )*
446                    ZoneRecordData::Unknown(ref inner) => inner.fmt(f),
447                }
448            }
449        }
450
451        //--- Debug
452
453        impl<O, N> core::fmt::Debug for ZoneRecordData<O, N>
454        where
455            O: AsRef<[u8]>,
456            N: core ::fmt::Debug
457        {
458            fn fmt(&self, f: &mut core::fmt::Formatter)
459                   -> core::fmt::Result {
460                match *self {
461                    $( $( $(
462                        ZoneRecordData::$mtype(ref inner) => {
463                            f.write_str(
464                                concat!(
465                                    "ZoneRecordData::",
466                                    stringify!($mtype),
467                                    "("
468                                )
469                            )?;
470                            core::fmt::Debug::fmt(inner, f)?;
471                            f.write_str(")")
472                        }
473                    )* )* )*
474                    ZoneRecordData::Unknown(ref inner) => {
475                        f.write_str("ZoneRecordData::Unknown(")?;
476                        core::fmt::Debug::fmt(inner, f)?;
477                        f.write_str(")")
478                    }
479                }
480            }
481        }
482
483        //------------- AllRecordData ----------------------------------------
484
485        /// Record data for all record types.
486        ///
487        /// This enum collects the record data types for all currently
488        /// implemented record types.
489        #[derive(Clone)]
490        #[non_exhaustive]
491        pub enum AllRecordData<O, N> {
492            $( $( $(
493                $mtype($mtype $( < $( $mn ),* > )*),
494            )* )* )*
495            $( $( $(
496                $ptype($ptype $( < $( $pn ),* > )*),
497            )* )* )*
498            Opt($crate::base::opt::Opt<O>),
499            Unknown($crate::base::rdata::UnknownRecordData<O>),
500        }
501
502        impl<O, N> AllRecordData<O, N> {
503            fn rtype(&self) -> $crate::base::iana::Rtype {
504                use $crate::base::rdata::RecordData;
505
506                match *self {
507                    $( $( $(
508                        AllRecordData::$mtype(ref inner) => {
509                            inner.rtype()
510                        }
511                    )* )* )*
512                    $( $( $(
513                        AllRecordData::$ptype(ref inner) => {
514                            inner.rtype()
515                        }
516                    )* )* )*
517
518                    AllRecordData::Opt(_) => $crate::base::iana::Rtype::Opt,
519                    AllRecordData::Unknown(ref inner) => inner.rtype(),
520                }
521            }
522        }
523
524        //--- From and Into
525
526        $( $( $(
527            impl<O, N> From<$mtype $( < $( $mn ),* > )*>
528            for AllRecordData<O, N> {
529                fn from(value: $mtype $( < $( $mn ),* >)*) -> Self {
530                    AllRecordData::$mtype(value)
531                }
532            }
533        )* )* )*
534
535        $( $( $(
536            impl<O, N> From<$ptype $( < $( $pn ),* > )*>
537            for AllRecordData<O, N> {
538                fn from(value: $ptype $( < $( $pn ),* >)*) -> Self {
539                    AllRecordData::$ptype(value)
540                }
541            }
542        )* )* )*
543
544        impl<O, N> From<$crate::base::opt::Opt<O>> for AllRecordData<O, N> {
545            fn from(value: $crate::base::opt::Opt<O>) -> Self {
546                AllRecordData::Opt(value)
547            }
548        }
549
550        impl<O, N> From<$crate::base::rdata::UnknownRecordData<O>>
551        for AllRecordData<O, N> {
552            fn from(
553                value: $crate::base::rdata::UnknownRecordData<O>
554            ) -> Self {
555                AllRecordData::Unknown(value)
556            }
557        }
558
559        impl<O, N> From<AllRecordData<O, N>>
560        for Result<ZoneRecordData<O, N>, AllRecordData<O, N>> {
561            fn from(
562                value: AllRecordData<O, N>
563            ) -> Result<ZoneRecordData<O, N>, AllRecordData<O, N>> {
564                match value {
565                    $( $( $(
566                        AllRecordData::$mtype(inner) => {
567                            Ok(ZoneRecordData::$mtype(inner))
568                        }
569                    )* )* )*
570                    AllRecordData::Unknown(inner) => {
571                        Ok(ZoneRecordData::Unknown(inner))
572                    }
573                    value => Err(value),
574                }
575            }
576        }
577
578        //--- OctetsFrom
579
580        impl<Octets, SrcOctets, Name, SrcName>
581            octseq::octets::OctetsFrom<
582                AllRecordData<SrcOctets, SrcName>
583            >
584            for AllRecordData<Octets, Name>
585        where
586            Octets: octseq::octets::OctetsFrom<SrcOctets>,
587            Name: octseq::octets::OctetsFrom<
588                SrcName, Error = Octets::Error,
589            >,
590        {
591            type Error = Octets::Error;
592
593            fn try_octets_from(
594                source: AllRecordData<SrcOctets, SrcName>
595            ) -> Result<Self, Self::Error> {
596                match source {
597                    $( $( $(
598                        AllRecordData::$mtype(inner) => {
599                            inner.convert_octets().map(
600                                AllRecordData::$mtype
601                            )
602                        }
603                    )* )* )*
604                    $( $( $(
605                        AllRecordData::$ptype(inner) => {
606                            inner.convert_octets().map(
607                                AllRecordData::$ptype
608                            )
609                        }
610                    )* )* )*
611                    AllRecordData::Opt(inner) => {
612                        Ok(AllRecordData::Opt(
613                            $crate::base::opt::Opt::try_octets_from(inner)?
614                        ))
615                    }
616                    AllRecordData::Unknown(inner) => {
617                        Ok(AllRecordData::Unknown(
618                            $crate::base::rdata::UnknownRecordData
619                                ::try_octets_from(inner)?
620                        ))
621                    }
622                }
623            }
624        }
625
626        //--- FlattenInto
627
628        impl<Octets, TargetOctets, Name, TargetName>
629            crate::base::name::FlattenInto<
630                AllRecordData<TargetOctets, TargetName>
631            >
632            for AllRecordData<Octets, Name>
633        where
634            TargetOctets: OctetsFrom<Octets>,
635            Name: crate::base::name::FlattenInto<
636                TargetName,
637                AppendError = TargetOctets::Error,
638            >,
639        {
640            type AppendError = TargetOctets::Error;
641
642            fn try_flatten_into(
643                self
644            ) -> Result<
645                AllRecordData<TargetOctets, TargetName>,
646                Self::AppendError
647            > {
648                match self {
649                    $( $( $(
650                        AllRecordData::$mtype(inner) => {
651                            inner.flatten().map(
652                                AllRecordData::$mtype
653                            )
654                        }
655                    )* )* )*
656                    $( $( $(
657                        AllRecordData::$ptype(inner) => {
658                            inner.flatten().map(
659                                AllRecordData::$ptype
660                            )
661                        }
662                    )* )* )*
663                    AllRecordData::Opt(inner) => {
664                        Ok(AllRecordData::Opt(
665                            $crate::base::opt::Opt::try_octets_from(inner)?
666                        ))
667                    }
668                    AllRecordData::Unknown(inner) => {
669                        Ok(AllRecordData::Unknown(
670                            $crate::base::rdata::
671                            UnknownRecordData::try_octets_from(inner)?
672                        ))
673                    }
674                }
675            }
676        }
677
678
679        //--- PartialEq and Eq
680
681        impl<O, OO, N, NN> PartialEq<AllRecordData<OO, NN>>
682        for AllRecordData<O, N>
683        where
684            O: AsRef<[u8]>, OO: AsRef<[u8]>,
685            N: $crate::base::name::ToDname, NN: $crate::base::name::ToDname
686        {
687            fn eq(&self, other: &AllRecordData<OO, NN>) -> bool {
688                match (self, other) {
689                    $( $( $(
690                        (
691                            &AllRecordData::$mtype(ref left),
692                            &AllRecordData::$mtype(ref right)
693                        ) => {
694                            left.eq(right)
695                        }
696                    )* )* )*
697                    $( $( $(
698                        (
699                            &AllRecordData::$ptype(ref left),
700                            &AllRecordData::$ptype(ref right)
701                        ) => {
702                            left.eq(right)
703                        }
704                    )* )* )*
705                    (_, _) => false
706                }
707            }
708        }
709
710        impl<O, N> Eq for AllRecordData<O, N>
711        where O: AsRef<[u8]>, N: $crate::base::name::ToDname { }
712
713
714        //--- Hash
715
716        impl<O, N> core::hash::Hash for AllRecordData<O, N>
717        where O: AsRef<[u8]>, N: core::hash::Hash {
718            fn hash<H: core::hash::Hasher>(&self, state: &mut H) {
719                self.rtype().hash(state);
720                match *self {
721                    $( $( $(
722                        AllRecordData::$mtype(ref inner) => {
723                            inner.hash(state)
724                        }
725                    )* )* )*
726                    $( $( $(
727                        AllRecordData::$ptype(ref inner) => {
728                            inner.hash(state)
729                        }
730                    )* )* )*
731                    AllRecordData::Opt(ref inner) => {
732                        inner.hash(state);
733                    }
734                    AllRecordData::Unknown(ref inner) => {
735                        inner.data().as_ref().hash(state);
736                    }
737                }
738            }
739        }
740
741        //--- RecordData and ParseRecordData
742
743        impl<O, N> $crate::base::rdata::RecordData for AllRecordData<O, N> {
744            fn rtype(&self) -> $crate::base::iana::Rtype {
745                match *self {
746                    $( $( $(
747                        AllRecordData::$mtype(ref inner) => {
748                            inner.rtype()
749                        }
750                    )* )* )*
751                    $( $( $(
752                        AllRecordData::$ptype(ref inner) => {
753                            inner.rtype()
754                        }
755                    )* )* )*
756                    AllRecordData::Opt(ref inner) => inner.rtype(),
757                    AllRecordData::Unknown(ref inner) => inner.rtype(),
758                }
759            }
760        }
761
762        impl<'a, Octs: octseq::octets::Octets>
763        $crate::base::rdata::ParseRecordData<'a, Octs>
764        for AllRecordData<Octs::Range<'a>, ParsedDname<Octs::Range<'a>>> {
765            fn parse_rdata(
766                rtype: $crate::base::iana::Rtype,
767                parser: &mut octseq::parse::Parser<'a, Octs>,
768            ) -> Result<Option<Self>, crate::base::wire::ParseError> {
769                match rtype {
770                    $( $( $(
771                        $crate::base::iana::Rtype::$mtype => {
772                            Ok(Some(AllRecordData::$mtype(
773                                $mtype::parse(parser)?
774                            )))
775                        }
776                    )* )* )*
777                    $( $( $(
778                        $crate::base::iana::Rtype::$ptype => {
779                            Ok(Some(AllRecordData::$ptype(
780                                $ptype::parse(parser)?
781                            )))
782                        }
783                    )* )* )*
784                    $crate::base::iana::Rtype::Opt => {
785                        Ok(Some(AllRecordData::Opt(
786                            $crate::base::opt::Opt::parse(parser)?
787                        )))
788                    }
789                    _ => {
790                        Ok($crate::base::rdata::UnknownRecordData::parse_rdata(
791                            rtype, parser
792                        )?.map(AllRecordData::Unknown))
793                    }
794                }
795            }
796        }
797
798        impl<Octs, Name> ComposeRecordData for AllRecordData<Octs, Name>
799        where Octs: AsRef<[u8]>, Name: ToDname {
800            fn rdlen(&self, compress: bool) -> Option<u16> {
801                match *self {
802                    $( $( $(
803                        AllRecordData::$mtype(ref inner) => {
804                            inner.rdlen(compress)
805                        }
806                    )* )* )*
807                    $( $( $(
808                        AllRecordData::$ptype(ref inner) => {
809                            inner.rdlen(compress)
810                        }
811                    )* )* )*
812                    AllRecordData::Opt(ref inner) => {
813                        inner.rdlen(compress)
814                    }
815                    AllRecordData::Unknown(ref inner) => {
816                        inner.rdlen(compress)
817                    }
818                }
819            }
820
821            fn compose_rdata<Target: Composer + ?Sized>(
822                &self, target: &mut Target
823            ) -> Result<(), Target::AppendError> {
824                match *self {
825                    $( $( $(
826                        AllRecordData::$mtype(ref inner) => {
827                            inner.compose_rdata(target)
828                        }
829                    )* )* )*
830                    $( $( $(
831                        AllRecordData::$ptype(ref inner) => {
832                            inner.compose_rdata(target)
833                        }
834                    )* )* )*
835                    AllRecordData::Opt(ref inner) => {
836                        inner.compose_rdata(target)
837                    }
838                    AllRecordData::Unknown(ref inner) => {
839                        inner.compose_rdata(target)
840                    }
841                }
842            }
843
844            fn compose_canonical_rdata<Target: Composer + ?Sized>(
845                &self, target: &mut Target
846            ) -> Result<(), Target::AppendError> {
847                match *self {
848                    $( $( $(
849                        AllRecordData::$mtype(ref inner) => {
850                            inner.compose_canonical_rdata(target)
851                        }
852                    )* )* )*
853                    $( $( $(
854                        AllRecordData::$ptype(ref inner) => {
855                            inner.compose_canonical_rdata(target)
856                        }
857                    )* )* )*
858                    AllRecordData::Opt(ref inner) => {
859                        inner.compose_canonical_rdata(target)
860                    }
861                    AllRecordData::Unknown(ref inner) => {
862                        inner.compose_canonical_rdata(target)
863                    }
864                }
865            }
866        }
867
868
869        //--- Display and Debug
870
871        impl<O, N> core::fmt::Display for AllRecordData<O, N>
872        where O: octseq::octets::Octets, N: core::fmt::Display {
873            fn fmt(
874                &self, f: &mut core::fmt::Formatter
875            ) -> core::fmt::Result {
876                match *self {
877                    $( $( $(
878                        AllRecordData::$mtype(ref inner) => {
879                            inner.fmt(f)
880                        }
881                    )* )* )*
882                    $( $( $(
883                        AllRecordData::$ptype(ref inner) => {
884                            inner.fmt(f)
885                        }
886                    )* )* )*
887                    AllRecordData::Opt(ref inner) => inner.fmt(f),
888                    AllRecordData::Unknown(ref inner) => inner.fmt(f),
889                }
890            }
891        }
892
893        impl<O, N> core::fmt::Debug for AllRecordData<O, N>
894        where O: octseq::octets::Octets, N: core::fmt::Debug {
895            fn fmt(
896                &self, f: &mut core::fmt::Formatter
897            ) -> core::fmt::Result {
898                match *self {
899                    $( $( $(
900                        AllRecordData::$mtype(ref inner) => {
901                            f.write_str(
902                                concat!(
903                                    "AllRecordData::",
904                                    stringify!($mtype),
905                                    "("
906                                )
907                            )?;
908                            core::fmt::Debug::fmt(inner, f)?;
909                            f.write_str(")")
910                        }
911                    )* )* )*
912                    $( $( $(
913                        AllRecordData::$ptype(ref inner) => {
914                            f.write_str(
915                                concat!(
916                                    "AllRecordData::",
917                                    stringify!($ptype),
918                                    "("
919                                )
920                            )?;
921                            core::fmt::Debug::fmt(inner, f)?;
922                            f.write_str(")")
923                        }
924                    )* )* )*
925                    AllRecordData::Opt(ref inner) => {
926                        f.write_str("AllRecordData::Opt(")?;
927                        core::fmt::Debug::fmt(inner, f)?;
928                        f.write_str(")")
929                    }
930                    AllRecordData::Unknown(ref inner) => {
931                        f.write_str("AllRecordData::Unknown(")?;
932                        core::fmt::Debug::fmt(inner, f)?;
933                        f.write_str(")")
934                    }
935                }
936            }
937        }
938
939    }
940}
941
942//------------ dname_type! --------------------------------------------------
943
944/// A macro for implementing a record data type with a single domain name.
945///
946/// Implements some basic methods plus the `RecordData`, `FlatRecordData`,
947/// and `Display` traits.
948macro_rules! dname_type_base {
949    ($(#[$attr:meta])* (
950        $target:ident, $rtype:ident, $field:ident, $into_field:ident
951    ) ) => {
952        $(#[$attr])*
953        #[derive(Clone, Debug)]
954        #[cfg_attr(
955            feature = "serde",
956            derive(serde::Serialize, serde::Deserialize)
957        )]
958        pub struct $target<N: ?Sized> {
959            $field: N
960        }
961
962        impl<N> $target<N> {
963            pub fn new($field: N) -> Self {
964                $target { $field }
965            }
966
967            pub fn $field(&self) -> &N {
968                &self.$field
969            }
970
971            pub fn $into_field(self) -> N {
972                self.$field
973            }
974
975            pub fn scan<S: crate::base::scan::Scanner<Dname = N>>(
976                scanner: &mut S
977            ) -> Result<Self, S::Error> {
978                scanner.scan_dname().map(Self::new)
979            }
980
981            pub(super) fn convert_octets<Target: OctetsFrom<N>>(
982                self
983            ) -> Result<$target<Target>, Target::Error> {
984                Target::try_octets_from(self.$field).map($target::new)
985            }
986
987            #[allow(dead_code)] // XXX Remove
988            pub(super) fn flatten<Target>(
989                self
990            ) -> Result<$target<Target>, N::AppendError>
991            where
992                N: crate::base::name::FlattenInto<Target>
993            {
994                self.$field.try_flatten_into().map($target::new)
995            }
996        }
997
998        impl<Octs: Octets> $target<ParsedDname<Octs>> {
999            pub fn parse<'a, Src: Octets<Range<'a> = Octs> + ?Sized + 'a>(
1000                parser: &mut Parser<'a, Src>,
1001            ) -> Result<Self, ParseError> {
1002                ParsedDname::parse(parser).map(Self::new)
1003            }
1004        }
1005
1006        //--- From and FromStr
1007
1008        impl<N> From<N> for $target<N> {
1009            fn from(name: N) -> Self {
1010                Self::new(name)
1011            }
1012        }
1013
1014        impl<N: FromStr> FromStr for $target<N> {
1015            type Err = N::Err;
1016
1017            fn from_str(s: &str) -> Result<Self, Self::Err> {
1018                N::from_str(s).map(Self::new)
1019            }
1020        }
1021
1022
1023        //--- OctetsFrom
1024
1025        impl<Name, SrcName> OctetsFrom<$target<SrcName>> for $target<Name>
1026        where Name: OctetsFrom<SrcName> {
1027            type Error = Name::Error;
1028
1029            fn try_octets_from(
1030                source: $target<SrcName>
1031            ) -> Result<Self, Self::Error> {
1032                Name::try_octets_from(source.$field).map(|name| {
1033                    Self::new(name)
1034                })
1035            }
1036        }
1037
1038        //--- FlattenInto
1039
1040        impl<Name, Target> crate::base::name::FlattenInto<$target<Target>>
1041        for $target<Name>
1042        where Name: crate::base::name::FlattenInto<Target> {
1043            type AppendError = Name::AppendError;
1044
1045            fn try_flatten_into(
1046                self
1047            ) -> Result<$target<Target>, Self::AppendError> {
1048                self.$field.try_flatten_into().map($target::new)
1049            }
1050        }
1051
1052        //--- PartialEq and Eq
1053
1054        impl<N, NN> PartialEq<$target<NN>> for $target<N>
1055        where N: ToDname, NN: ToDname {
1056            fn eq(&self, other: &$target<NN>) -> bool {
1057                self.$field.name_eq(&other.$field)
1058            }
1059        }
1060
1061        impl<N: ToDname> Eq for $target<N> { }
1062
1063
1064        //--- PartialOrd and Ord
1065        //
1066        // For CanonicalOrd, see below.
1067
1068        impl<N, NN> PartialOrd<$target<NN>> for $target<N>
1069        where N: ToDname, NN: ToDname {
1070            fn partial_cmp(&self, other: &$target<NN>) -> Option<Ordering> {
1071                Some(self.$field.name_cmp(&other.$field))
1072            }
1073        }
1074
1075        impl<N: ToDname> Ord for $target<N> {
1076            fn cmp(&self, other: &Self) -> Ordering {
1077                self.$field.name_cmp(&other.$field)
1078            }
1079        }
1080
1081        //--- Hash
1082
1083        impl<N: hash::Hash> hash::Hash for $target<N> {
1084            fn hash<H: hash::Hasher>(&self, state: &mut H) {
1085                self.$field.hash(state)
1086            }
1087        }
1088
1089        //--- RecordData, ParseRecordData
1090
1091        impl<N> $crate::base::rdata::RecordData for $target<N> {
1092            fn rtype(&self) -> $crate::base::iana::Rtype {
1093                $crate::base::iana::Rtype::$rtype
1094            }
1095        }
1096
1097        impl<'a, Octs> $crate::base::rdata::ParseRecordData<'a, Octs>
1098        for $target<$crate::base::name::ParsedDname<Octs::Range<'a>>>
1099        where Octs: octseq::octets::Octets + ?Sized {
1100            fn parse_rdata(
1101                rtype: $crate::base::iana::Rtype,
1102                parser: &mut octseq::parse::Parser<'a, Octs>,
1103            ) -> Result<Option<Self>, $crate::base::wire::ParseError> {
1104                if rtype == $crate::base::iana::Rtype::$rtype {
1105                    Self::parse(parser).map(Some)
1106                }
1107                else {
1108                    Ok(None)
1109                }
1110            }
1111        }
1112
1113        //--- Display
1114
1115        impl<N: fmt::Display> fmt::Display for $target<N> {
1116            fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
1117                write!(f, "{}.", self.$field)
1118            }
1119        }
1120    }
1121}
1122
1123macro_rules! dname_type_well_known {
1124    ($(#[$attr:meta])* (
1125        $target:ident, $rtype:ident, $field:ident, $into_field:ident
1126    ) ) => {
1127        dname_type_base! {
1128            $( #[$attr] )*
1129            ($target, $rtype, $field, $into_field)
1130        }
1131
1132        impl<N: ToDname> $crate::base::rdata::ComposeRecordData
1133        for $target<N> {
1134            fn rdlen(&self, compress: bool) -> Option<u16> {
1135                if compress {
1136                    None
1137                }
1138                else {
1139                    Some(self.$field.compose_len())
1140                }
1141            }
1142
1143            fn compose_rdata<Target: $crate::base::wire::Composer + ?Sized>(
1144                &self, target: &mut Target
1145            ) -> Result<(), Target::AppendError> {
1146                if target.can_compress() {
1147                    target.append_compressed_dname(&self.$field)
1148                }
1149                else {
1150                    self.$field.compose(target)
1151                }
1152            }
1153
1154            fn compose_canonical_rdata<Target>(
1155                &self, target: &mut Target
1156            ) -> Result<(), Target::AppendError>
1157            where Target: $crate::base::wire::Composer + ?Sized {
1158                self.$field.compose_canonical(target)
1159            }
1160        }
1161
1162        impl<N: ToDname, NN: ToDname> CanonicalOrd<$target<NN>> for $target<N> {
1163            fn canonical_cmp(&self, other: &$target<NN>) -> Ordering {
1164                self.$field.lowercase_composed_cmp(&other.$field)
1165            }
1166        }
1167    }
1168}
1169
1170macro_rules! dname_type_canonical {
1171    ($(#[$attr:meta])* (
1172        $target:ident, $rtype:ident, $field:ident, $into_field:ident
1173    ) ) => {
1174        dname_type_base! {
1175            $( #[$attr] )*
1176            ($target, $rtype, $field, $into_field)
1177        }
1178
1179        impl<N: ToDname> $crate::base::rdata::ComposeRecordData
1180        for $target<N> {
1181            fn rdlen(&self, _compress: bool) -> Option<u16> {
1182                Some(self.$field.compose_len())
1183            }
1184
1185            fn compose_rdata<Target: $crate::base::wire::Composer + ?Sized>(
1186                &self, target: &mut Target
1187            ) -> Result<(), Target::AppendError> {
1188                self.$field.compose(target)
1189            }
1190
1191            fn compose_canonical_rdata<Target>(
1192                &self, target: &mut Target
1193            ) -> Result<(), Target::AppendError>
1194            where Target: $crate::base::wire::Composer + ?Sized {
1195                self.$field.compose_canonical(target)
1196            }
1197        }
1198
1199        impl<N: ToDname, NN: ToDname> CanonicalOrd<$target<NN>> for $target<N> {
1200            fn canonical_cmp(&self, other: &$target<NN>) -> Ordering {
1201                self.$field.lowercase_composed_cmp(&other.$field)
1202            }
1203        }
1204    }
1205}
1206
1207#[allow(unused_macros)]
1208macro_rules! dname_type {
1209    ($(#[$attr:meta])* (
1210        $target:ident, $rtype:ident, $field:ident, $into_field:ident
1211    ) ) => {
1212        dname_type_base! {
1213            $( #[$attr] )*
1214            ($target, $rtype, $field, $into_field)
1215        }
1216
1217        impl<N: ToDname> $crate::base::rdata::ComposeRecordData
1218        for $target<N> {
1219            fn rdlen(&self, _compress: bool) -> Option<u16> {
1220                Some(self.compose_len)
1221            }
1222
1223            fn compose_rdata<Target: $crate::base::wire::Composer + ?Sized>(
1224                &self, target: &mut Target
1225            ) -> Result<(), Target::AppendError> {
1226                self.$field.compose(target)
1227            }
1228
1229            fn compose_canonical_rdata<Target>(
1230                &self, target: &mut Target
1231            ) -> Result<(), Target::AppendError>
1232            where Target: $crate::base::wire::Composer + ?Sized {
1233                self.$field.compose(target)
1234            }
1235        }
1236
1237        impl<N: ToDname, NN: ToDname> CanonicalOrd<$target<NN>> for $target<N> {
1238            fn canonical_cmp(&self, other: &$target<NN>) -> Ordering {
1239                self.$field.name_cmp(&other.$field)
1240            }
1241        }
1242    }
1243}