1use core::ops::Range;
2
3use byteorder::{ByteOrder, NetworkEndian};
4
5use super::{assert, BoundsError, CharacterString, CharacterStrings, Name, NameError, View};
6use crate::zone::Format;
7
8macro_rules! declare_rdata {
9 ($($ty:ident,)*) => {
10 #[non_exhaustive]
11 pub enum Rdata<'s> {
12 $($ty($ty<'s>),)*
13 }
14 $(impl<'s> From<$ty<'s>> for Rdata<'s> {
15 fn from(inner: $ty<'s>) -> Self {
16 Self::$ty(inner)
17 }
18 })*
19 impl<'s> AsRef<dyn View<'s, Error = RdataError>> for Rdata<'s> {
20 fn as_ref(&self) -> &dyn View<'s, Error = RdataError> {
21 match self {
22 $(Self::$ty(x) => x,)*
23 }
24 }
25 }
26 impl<'s> AsRef<dyn Format + 's> for Rdata<'s> {
27 fn as_ref(&self) -> &(dyn Format + 's) {
28 match self {
29 $(Self::$ty(x) => x,)*
30 }
31 }
32 }
33 };
34}
35
36declare_rdata! {
37 Malformed,
38 Unknown,
39 Soa,
40 Mx,
41 Txt,
42 Caa,
43 CompressibleName,
44 InAddress,
45 InAaaa,
46}
47
48pub struct Soa<'s> {
49 pub source: &'s [u8],
50 pub offset: usize,
51 pub mname_len: usize,
52 pub rname_len: usize,
53}
54
55pub struct Mx<'s> {
56 pub source: &'s [u8],
57 pub offset: usize,
58 pub exchange_len: usize,
59}
60
61pub struct Txt<'s> {
62 pub source: &'s [u8],
63 pub offset: usize,
64 pub len: usize,
65}
66
67pub struct Caa<'s> {
68 pub source: &'s [u8],
69 pub offset: usize,
70 pub tag_len: usize,
71 pub value_len: usize,
72}
73
74pub struct CaaTag<'s> {
75 pub source: &'s [u8],
76 pub offset: usize,
77 pub len: usize,
78}
79
80pub struct CaaValue<'s> {
81 pub source: &'s [u8],
82 pub offset: usize,
83 pub len: usize,
84}
85
86pub struct CompressibleName<'s> {
87 pub name: Name<'s>,
88}
89
90pub struct InAddress<'s> {
91 pub source: &'s [u8],
92 pub offset: usize,
93}
94
95pub struct InAaaa<'s> {
96 pub source: &'s [u8],
97 pub offset: usize,
98}
99
100pub struct Malformed<'s> {
101 pub inner: Unknown<'s>,
102}
103
104pub struct Unknown<'s> {
105 pub source: &'s [u8],
106 pub offset: usize,
107 pub len: usize,
108}
109
110error!(RdataError(s(s.as_ref()), __));
111#[derive(Debug, displaydoc::Display)]
112pub struct RdataError(RdataError0, &'static str);
114
115#[cfg(feature = "std")]
116pub type RdataError0 = eyre::Error;
117#[cfg(not(feature = "std"))]
118pub type RdataError0 = ();
119
120error!(SoaError, Bounds, Name);
121#[derive(Debug, displaydoc::Display)]
123#[prefix_enum_doc_attributes]
124pub enum SoaError {
125 Bounds(BoundsError),
127
128 Name(NameError),
130}
131
132impl RdataError {
133 #[cfg(feature = "std")]
134 fn new<E: 'static + Send + Sync + std::error::Error>(error: E, ty: &'static str) -> Self {
135 Self(error.into(), ty)
136 }
137 #[cfg(not(feature = "std"))]
138 fn new<E: 'static + Send + Sync>(_: E, ty: &'static str) -> Self {
139 Self((), ty)
140 }
141}
142
143trait RdataResultExt<T> {
144 fn into_rdata_error<V>(self) -> Result<T, RdataError>;
145}
146
147#[cfg(feature = "std")]
148impl<T, E: 'static + Send + Sync + std::error::Error> RdataResultExt<T> for Result<T, E> {
149 fn into_rdata_error<V>(self) -> Result<T, RdataError> {
150 self.map_err(|e| RdataError::new(e, core::any::type_name::<V>()))
151 }
152}
153#[cfg(not(feature = "std"))]
154impl<T, E: 'static + Send + Sync> RdataResultExt<T> for Result<T, E> {
155 fn into_rdata_error<V>(self) -> Result<T, RdataError> {
156 self.map_err(|e| RdataError::new(e, core::any::type_name::<V>()))
157 }
158}
159
160impl Soa<'_> {
161 pub fn mname(&self) -> Name {
162 Name {
163 source: self.source,
164 offset: self.offset,
165 len: self.mname_len,
166 }
167 }
168
169 pub fn rname(&self) -> Name {
170 Name {
171 source: self.source,
172 offset: self.offset + self.mname_len,
173 len: self.rname_len,
174 }
175 }
176
177 pub fn serial(&self) -> u32 {
178 let offset = self.mname_len + self.rname_len;
179
180 NetworkEndian::read_u32(&self.source[self.offset..][offset..])
181 }
182
183 pub fn refresh(&self) -> u32 {
184 let offset = self.mname_len + self.rname_len + 4;
185
186 NetworkEndian::read_u32(&self.source[self.offset..][offset..])
187 }
188
189 pub fn retry(&self) -> u32 {
190 let offset = self.mname_len + self.rname_len + 8;
191
192 NetworkEndian::read_u32(&self.source[self.offset..][offset..])
193 }
194
195 pub fn expire(&self) -> u32 {
196 let offset = self.mname_len + self.rname_len + 12;
197
198 NetworkEndian::read_u32(&self.source[self.offset..][offset..])
199 }
200
201 pub fn minimum(&self) -> u32 {
202 let offset = self.mname_len + self.rname_len + 16;
203
204 NetworkEndian::read_u32(&self.source[self.offset..][offset..])
205 }
206}
207
208impl Mx<'_> {
209 pub fn preference(&self) -> u16 {
210 NetworkEndian::read_u16(&self.source[self.offset..])
211 }
212
213 pub fn exchange(&self) -> Name {
214 Name {
215 source: self.source,
216 offset: self.offset + 2,
217 len: self.exchange_len,
218 }
219 }
220}
221
222impl Txt<'_> {
223 pub fn data(&self) -> CharacterStrings<'_> {
224 let start = self.offset;
225 let stop = self.offset + self.len;
226
227 CharacterStrings::new(self.source, start..stop)
228 }
229}
230
231impl Caa<'_> {
232 pub fn flags(&self) -> u8 {
233 self.source[self.offset]
234 }
235
236 pub fn critical(&self) -> bool {
237 self.flags() >> 7 & 1 == 1
238 }
239
240 pub fn tag(&self) -> CaaTag {
241 CaaTag {
242 source: self.source,
243 offset: self.offset + 2,
244 len: self.tag_len,
245 }
246 }
247
248 pub fn value(&self) -> CaaValue {
249 CaaValue {
250 source: self.source,
251 offset: self.offset + 2 + self.tag_len,
252 len: self.value_len,
253 }
254 }
255}
256
257impl<'s> View<'s> for Soa<'s> {
258 type Error = RdataError;
259
260 fn view(source: &'s [u8], range: Range<usize>) -> super::Result<Self, Self::Error> {
261 let (_, rest) = Name::view(source, range.clone())
262 .map_err(SoaError::Name)
263 .into_rdata_error::<Self>()?;
264 let mname_len = rest.start - range.start;
265
266 let (_, mut rest) = Name::view(source, rest)
267 .map_err(SoaError::Name)
268 .into_rdata_error::<Self>()?;
269 let rname_len = rest.start - range.start - mname_len;
270
271 assert(source, &rest, 20)
272 .map_err(SoaError::Bounds)
273 .into_rdata_error::<Self>()?;
274 rest.start += 20;
275
276 Ok((
277 Soa {
278 source,
279 offset: range.start,
280 mname_len,
281 rname_len,
282 },
283 rest,
284 ))
285 }
286
287 fn len(&self) -> usize {
288 self.mname_len + self.rname_len + 20
289 }
290}
291
292impl<'s> View<'s> for Mx<'s> {
293 type Error = RdataError;
294
295 fn view(source: &'s [u8], range: Range<usize>) -> super::Result<Self, Self::Error> {
296 let mut rest = range.clone();
297
298 assert(source, &rest, 2).into_rdata_error::<Self>()?;
299 rest.start += 2;
300
301 let (_, rest) = Name::view(source, rest)
302 .map_err(SoaError::Name)
303 .into_rdata_error::<Self>()?;
304 let exchange_len = rest.start - range.start - 2;
305
306 Ok((
307 Mx {
308 source,
309 offset: range.start,
310 exchange_len,
311 },
312 rest,
313 ))
314 }
315
316 fn len(&self) -> usize {
317 2 + self.exchange_len
318 }
319}
320
321impl<'s> View<'s> for Txt<'s> {
322 type Error = RdataError;
323
324 fn view(source: &'s [u8], range: Range<usize>) -> super::Result<Self, Self::Error> {
325 let mut next = range.clone();
326
327 while next.start != next.end {
328 let (_, rest) = CharacterString::view(source, next).into_rdata_error::<Self>()?;
329 next = rest;
330 }
331
332 let offset = range.start;
333 let len = next.start - offset;
334
335 Ok((
336 Txt {
337 source,
338 offset,
339 len,
340 },
341 next,
342 ))
343 }
344
345 fn len(&self) -> usize {
346 self.len
347 }
348}
349
350impl<'s> View<'s> for Caa<'s> {
351 type Error = RdataError;
352
353 fn view(source: &'s [u8], range: Range<usize>) -> super::Result<Self, Self::Error> {
354 let mut rest = range.clone();
355
356 assert(source, &rest, 1).into_rdata_error::<Self>()?;
357 rest.start += 1;
358
359 let (octet, mut rest) = u8::view(source, rest).into_rdata_error::<Self>()?;
360 let tag_len: usize = octet.into();
361
362 assert(source, &rest, tag_len).into_rdata_error::<Self>()?;
363 rest.start += tag_len;
364
365 let value_len = rest.end - rest.start;
367 rest.start += value_len;
368
369 Ok((
370 Caa {
371 source,
372 offset: range.start,
373 tag_len,
374 value_len,
375 },
376 rest,
377 ))
378 }
379
380 fn len(&self) -> usize {
381 1 + 1 + self.tag_len + self.value_len
382 }
383}
384
385impl<'s> View<'s> for CompressibleName<'s> {
386 type Error = RdataError;
387
388 fn view(source: &'s [u8], range: Range<usize>) -> super::Result<Self, Self::Error> {
389 let (name, rest) = Name::view(source, range).into_rdata_error::<Self>()?;
390
391 Ok((Self { name }, rest))
392 }
393
394 fn len(&self) -> usize {
395 self.name.len()
396 }
397}
398
399impl<'s> View<'s> for InAddress<'s> {
400 type Error = RdataError;
401
402 fn view(source: &'s [u8], mut range: Range<usize>) -> super::Result<Self, Self::Error> {
403 let offset = range.start;
404
405 assert(source, &range, 4).into_rdata_error::<Self>()?;
406 range.start += 4;
407
408 Ok((InAddress { source, offset }, range))
409 }
410
411 fn len(&self) -> usize {
412 4
413 }
414}
415
416impl<'s> View<'s> for InAaaa<'s> {
417 type Error = RdataError;
418
419 fn view(source: &'s [u8], mut range: Range<usize>) -> super::Result<Self, Self::Error> {
420 let offset = range.start;
421
422 assert(source, &range, 16).into_rdata_error::<Self>()?;
423 range.start += 16;
424
425 Ok((InAaaa { source, offset }, range))
426 }
427
428 fn len(&self) -> usize {
429 16
430 }
431}
432
433impl<'s> View<'s> for Malformed<'s> {
434 type Error = RdataError;
435
436 fn view(source: &'s [u8], range: Range<usize>) -> super::Result<Self, Self::Error> {
437 let (inner, range) = Unknown::view(source, range)?;
438
439 Ok((Malformed { inner }, range))
440 }
441
442 fn len(&self) -> usize {
443 self.inner.len()
444 }
445}
446
447impl<'s> View<'s> for Unknown<'s> {
448 type Error = RdataError;
449
450 fn view(source: &'s [u8], mut range: Range<usize>) -> super::Result<Self, Self::Error> {
451 let offset = range.start;
452 let len = range.end - offset;
453
454 assert(source, &range, len).into_rdata_error::<Self>()?;
455 range.start += len;
456
457 Ok((
458 Unknown {
459 source,
460 offset,
461 len,
462 },
463 range,
464 ))
465 }
466
467 fn len(&self) -> usize {
468 self.len
469 }
470}