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}