simple_dns/dns/rdata/
macros.rs1macro_rules! rr_wrapper {
2 (#[doc=$doc:expr] $t:ident: $w:ident = $c:literal) => {
3 #[derive(Debug, PartialEq, Eq, Hash, Clone)]
4 #[doc = $doc]
5 pub struct $t<'a>(pub $w<'a>);
6
7 impl<'a> RR for $t<'a> {
8 const TYPE_CODE: u16 = $c;
9 }
10
11 impl<'a> From<$w<'a>> for $t<'a> {
12 fn from(value: $w<'a>) -> Self {
13 $t(value)
14 }
15 }
16
17 impl<'a> $t<'a> {
18 pub fn into_owned<'b>(self) -> $t<'b> {
20 $t(self.0.into_owned())
21 }
22 }
23
24 impl<'a> WireFormat<'a> for $t<'a> {
25 fn parse(data: &'a [u8], position: &mut usize) -> crate::Result<Self>
26 where
27 Self: Sized,
28 {
29 $w::parse(data, position).map(|n| $t(n))
30 }
31
32 fn write_to<T: std::io::Write>(&self, out: &mut T) -> crate::Result<()> {
33 self.0.write_to(out)
34 }
35
36 fn write_compressed_to<T: std::io::Write + std::io::Seek>(
37 &'a self,
38 out: &mut T,
39 name_refs: &mut std::collections::HashMap<&'a [crate::dns::name::Label<'a>], usize>,
40 ) -> crate::Result<()> {
41 self.0.write_compressed_to(out, name_refs)
42 }
43
44 fn len(&self) -> usize {
45 self.0.len()
46 }
47 }
48
49 impl<'a> std::ops::Deref for $t<'a> {
50 type Target = $w<'a>;
51
52 fn deref(&self) -> &Self::Target {
53 &self.0
54 }
55 }
56
57 impl<'a> std::ops::DerefMut for $t<'a> {
58 fn deref_mut(&mut self) -> &mut Self::Target {
59 &mut self.0
60 }
61 }
62 };
63}
64
65macro_rules! rdata_enum {
66 ($($i:tt$(<$x:lifetime>)?,)+) => {
67 #[derive(Debug, Eq, PartialEq, Hash, Clone)]
69 #[allow(missing_docs)]
70 pub enum RData<'a> {
71 $(
72 $i($i$(<$x>)?),
73 )+
74
75 NULL(u16, NULL<'a>),
76 Empty(TYPE)
77 }
78
79 impl<'a> WireFormat<'a> for RData<'a> {
80 fn parse(data: &'a [u8], position: &mut usize) -> crate::Result<Self>
81 where
82 Self: Sized,
83 {
84 if *position + 10 > data.len() {
85 return Err(crate::SimpleDnsError::InsufficientData);
86 }
87
88 let rdatatype = u16::from_be_bytes(data[*position..*position + 2].try_into()?).into();
89 let rdatalen = u16::from_be_bytes(data[*position + 8..*position + 10].try_into()?) as usize;
90
91 if rdatatype == TYPE::OPT {
94 return Ok(RData::OPT(OPT::parse(&data[..*position + rdatalen + 10], position)?))
95 }
96 *position += 10;
97
98 if rdatalen == 0 {
99 return Ok(RData::Empty(rdatatype));
100 }
101
102 if *position + rdatalen > data.len() {
103 return Err(crate::SimpleDnsError::InsufficientData);
104 }
105
106 parse_rdata(&data[..*position + rdatalen], position, rdatatype)
107 }
108
109 fn write_to<T: std::io::Write>(
110 &self,
111 out: &mut T,
112 ) -> crate::Result<()> {
113 match &self {
114 $(
115 RData::$i(data) => data.write_to(out),
116 )+
117
118 RData::NULL(_, data) => data.write_to(out),
119 RData::Empty(_) => { Ok(()) },
120 }
121 }
122
123 fn write_compressed_to<T: std::io::Write + std::io::Seek>(
124 &'a self,
125 out: &mut T,
126 name_refs: &mut HashMap<&'a [crate::dns::name::Label<'a>], usize>,
127 ) -> crate::Result<()> {
128 match &self {
129 $(
130 RData::$i(data) => data.write_compressed_to(out, name_refs),
131 )+
132
133 RData::NULL(_, data) => data.write_compressed_to(out, name_refs),
134 RData::Empty(_) => { Ok(()) },
135 }
136 }
137
138 fn len(&self) -> usize {
139 match &self {
140 $(
141 RData::$i(data) => data.len(),
142 )+
143
144 RData::NULL(_, data) => data.len(),
145 RData::Empty(_) => 0,
146 }
147 }
148 }
149
150
151
152 impl<'a> RData<'a> {
153 pub fn type_code(&self) -> TYPE {
155 match self {
156 $(
157 RData::$i(_) => TYPE::$i,
158 )+
159
160 RData::NULL(type_code, _) => TYPE::Unknown(*type_code),
161 RData::Empty(ty) => *ty
162 }
163 }
164
165 pub fn into_owned<'b>(self) -> RData<'b> {
167 match self {
168 $(
169 RData::$i(data) => RData::$i(data.into_owned()),
170 )+
171
172 RData::NULL(rdatatype, data) => RData::NULL(rdatatype, data.into_owned()),
173 RData::Empty(ty) => RData::Empty(ty)
174 }
175 }
176 }
177
178 fn parse_rdata<'a>(data: &'a [u8], position: &mut usize, rdatatype: TYPE) -> crate::Result<RData<'a>> {
179 let rdata = match rdatatype {
180 $(
181 TYPE::$i => RData::$i($i::parse(data, position)?),
182 )+
183
184 TYPE::NULL => RData::NULL(rdatatype.into(), NULL::parse(data, position)?),
185 TYPE::Unknown(rdatatype) => RData::NULL(rdatatype, NULL::parse(data, position)?),
186 };
187
188 Ok(rdata)
189 }
190
191
192 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
195 #[allow(missing_docs)]
196 #[non_exhaustive]
197 pub enum TYPE {
198 $( $i,)+
199
200 NULL,
201 Unknown(u16)
202 }
203
204
205 impl From<TYPE> for u16 {
206 fn from(value: TYPE) -> Self {
207 match value {
208 $(
209 TYPE::$i => $i::TYPE_CODE,
210 )+
211
212 TYPE::NULL => NULL::TYPE_CODE,
213 TYPE::Unknown(x) => x,
214 }
215 }
216 }
217
218 impl From<u16> for TYPE {
219 fn from(value: u16) -> Self {
220 match value {
221 $(
222 $i::TYPE_CODE => TYPE::$i,
223 )+
224
225 NULL::TYPE_CODE => TYPE::NULL,
226 v => TYPE::Unknown(v),
227 }
228 }
229 }
230 }
231}
232
233pub(crate) use rdata_enum;
234pub(crate) use rr_wrapper;