Skip to main content

hickory_proto/rr/rdata/
name.rs

1// Copyright 2015-2023 Benjamin Fry <benjaminfry@me.com>
2//
3// Licensed under the Apache License, Version 2.0, <LICENSE-APACHE or
4// https://apache.org/licenses/LICENSE-2.0> or the MIT license <LICENSE-MIT or
5// https://opensource.org/licenses/MIT>, at your option. This file may not be
6// copied, modified, or distributed except according to those terms.
7
8//! Record type for all cname like records.
9//!
10//! A generic struct for all {*}NAME pointer RData records, CNAME, NS, and PTR. Here is the text for
11//! CNAME from RFC 1035, Domain Implementation and Specification, November 1987:
12//!
13//! [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
14//!
15//! ```text
16//! 3.3.1. CNAME RDATA format
17//!
18//!     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
19//!     /                     CNAME                     /
20//!     /                                               /
21//!     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
22//!
23//! where:
24//!
25//! CNAME           A <domain-name> which specifies the canonical or primary
26//!                 name for the owner.  The owner name is an alias.
27//!
28//! CNAME RRs cause no additional section processing, but name servers may
29//! choose to restart the query at the canonical name in certain cases.  See
30//! the description of name server logic in [RFC-1034] for details.
31//! ```
32
33use core::{fmt, ops::Deref};
34
35#[cfg(feature = "serde")]
36use serde::{Deserialize, Serialize};
37
38use crate::{
39    error::ProtoResult,
40    rr::{RData, RecordData, RecordType, domain::Name},
41    serialize::binary::*,
42};
43
44macro_rules! name_rdata {
45    ($name: ident, $rdata_policy: expr) => {
46        #[doc = stringify!(new type for the RecordData of $name)]
47        #[cfg_attr(feature = "serde", derive(Deserialize, Serialize))]
48        #[derive(Debug, PartialEq, Eq, Hash, Clone)]
49        pub struct $name(pub Name);
50
51        impl BinEncodable for $name {
52            fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
53                let mut encoder = encoder.with_rdata_behavior($rdata_policy);
54                self.0.emit(&mut encoder)
55            }
56        }
57
58        impl<'r> BinDecodable<'r> for $name {
59            fn read(decoder: &mut BinDecoder<'r>) -> Result<Self, DecodeError> {
60                Name::read(decoder).map(Self)
61            }
62        }
63
64        impl RecordData for $name {
65            fn try_borrow(data: &RData) -> Option<&Self> {
66                match data {
67                    RData::$name(data) => Some(data),
68                    _ => None,
69                }
70            }
71
72            fn record_type(&self) -> RecordType {
73                RecordType::$name
74            }
75
76            fn into_rdata(self) -> RData {
77                RData::$name(self)
78            }
79        }
80
81        impl Deref for $name {
82            type Target = Name;
83
84            fn deref(&self) -> &Self::Target {
85                &self.0
86            }
87        }
88
89        impl fmt::Display for $name {
90            fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
91                write!(f, "{}", self.0)
92            }
93        }
94    };
95}
96
97name_rdata!(CNAME, RDataEncoding::StandardRecord);
98name_rdata!(NS, RDataEncoding::StandardRecord);
99name_rdata!(PTR, RDataEncoding::StandardRecord);
100name_rdata!(ANAME, RDataEncoding::Other);
101
102#[cfg(test)]
103mod tests {
104    use alloc::string::ToString;
105
106    use super::*;
107
108    #[test]
109    fn test_it_to_string_should_not_stack_overflow() {
110        assert_eq!(PTR("abc.com".parse().unwrap()).to_string(), "abc.com");
111    }
112}