domain/rdata/
aaaa.rs
1use crate::base::cmp::CanonicalOrd;
8use crate::base::iana::Rtype;
9use crate::base::net::Ipv6Addr;
10use crate::base::rdata::{ComposeRecordData, ParseRecordData, RecordData};
11use crate::base::scan::{Scanner, ScannerError};
12use crate::base::wire::{Composer, Parse, ParseError};
13use core::cmp::Ordering;
14use core::convert::Infallible;
15use core::str::FromStr;
16use core::{fmt, str};
17use octseq::octets::OctetsFrom;
18use octseq::parse::Parser;
19
20#[derive(Clone, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
23#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
24pub struct Aaaa {
25 addr: Ipv6Addr,
26}
27
28impl Aaaa {
29 #[must_use]
30 pub fn new(addr: Ipv6Addr) -> Aaaa {
31 Aaaa { addr }
32 }
33
34 #[must_use]
35 pub fn addr(&self) -> Ipv6Addr {
36 self.addr
37 }
38 pub fn set_addr(&mut self, addr: Ipv6Addr) {
39 self.addr = addr
40 }
41
42 pub(super) fn convert_octets<E>(self) -> Result<Self, E> {
43 Ok(self)
44 }
45
46 pub(super) fn flatten<E>(self) -> Result<Self, E> {
47 Ok(self)
48 }
49
50 pub fn parse<Octs: AsRef<[u8]> + ?Sized>(
51 parser: &mut Parser<Octs>,
52 ) -> Result<Self, ParseError> {
53 Ipv6Addr::parse(parser).map(Self::new)
54 }
55
56 pub fn scan<S: Scanner>(scanner: &mut S) -> Result<Self, S::Error> {
57 let token = scanner.scan_octets()?;
58 let token = str::from_utf8(token.as_ref())
59 .map_err(|_| S::Error::custom("expected IPv6 address"))?;
60 Aaaa::from_str(token)
61 .map_err(|_| S::Error::custom("expected IPv6 address"))
62 }
63}
64
65impl From<Ipv6Addr> for Aaaa {
68 fn from(addr: Ipv6Addr) -> Self {
69 Self::new(addr)
70 }
71}
72
73impl From<Aaaa> for Ipv6Addr {
74 fn from(data: Aaaa) -> Self {
75 data.addr
76 }
77}
78
79impl FromStr for Aaaa {
80 type Err = <Ipv6Addr as core::str::FromStr>::Err;
81
82 fn from_str(s: &str) -> Result<Self, Self::Err> {
83 Ipv6Addr::from_str(s).map(Aaaa::new)
84 }
85}
86
87impl OctetsFrom<Aaaa> for Aaaa {
90 type Error = Infallible;
91
92 fn try_octets_from(source: Aaaa) -> Result<Self, Self::Error> {
93 Ok(source)
94 }
95}
96
97impl CanonicalOrd for Aaaa {
100 fn canonical_cmp(&self, other: &Self) -> Ordering {
101 self.cmp(other)
102 }
103}
104
105impl RecordData for Aaaa {
108 fn rtype(&self) -> Rtype {
109 Rtype::Aaaa
110 }
111}
112
113impl<'a, Octs: AsRef<[u8]> + ?Sized> ParseRecordData<'a, Octs> for Aaaa {
114 fn parse_rdata(
115 rtype: Rtype,
116 parser: &mut Parser<'a, Octs>,
117 ) -> Result<Option<Self>, ParseError> {
118 if rtype == Rtype::Aaaa {
119 Self::parse(parser).map(Some)
120 } else {
121 Ok(None)
122 }
123 }
124}
125
126impl ComposeRecordData for Aaaa {
127 fn rdlen(&self, _compress: bool) -> Option<u16> {
128 Some(16)
129 }
130
131 fn compose_rdata<Target: Composer + ?Sized>(
132 &self,
133 target: &mut Target,
134 ) -> Result<(), Target::AppendError> {
135 target.append_slice(&self.addr().octets())
136 }
137
138 fn compose_canonical_rdata<Target: Composer + ?Sized>(
139 &self,
140 target: &mut Target,
141 ) -> Result<(), Target::AppendError> {
142 self.compose_rdata(target)
143 }
144}
145
146impl fmt::Display for Aaaa {
149 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
150 self.addr.fmt(f)
151 }
152}
153
154impl AsRef<Ipv6Addr> for Aaaa {
157 fn as_ref(&self) -> &Ipv6Addr {
158 &self.addr
159 }
160}
161
162impl AsMut<Ipv6Addr> for Aaaa {
163 fn as_mut(&mut self) -> &mut Ipv6Addr {
164 &mut self.addr
165 }
166}
167
168#[cfg(test)]
171#[cfg(all(feature = "std", feature = "bytes"))]
172mod test {
173 use super::*;
174 use crate::base::rdata::test::{
175 test_compose_parse, test_rdlen, test_scan,
176 };
177
178 #[test]
179 fn aaaa_compose_parse_scan() {
180 let addr = "2001:db9::12:13";
181 let rdata = Aaaa::from_str(addr).unwrap();
182 test_rdlen(&rdata);
183 test_compose_parse(&rdata, Aaaa::parse);
184 test_scan(&[addr], Aaaa::scan, &rdata);
185 }
186}