hickory_proto/rr/rdata/
null.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//! null record type, generally not used except as an internal tool for representing null data
9use std::fmt;
10
11#[cfg(feature = "serde-config")]
12use serde::{Deserialize, Serialize};
13
14use crate::{
15    error::ProtoResult,
16    rr::{RData, RecordData, RecordDataDecodable, RecordType},
17    serialize::binary::{BinDecoder, BinEncodable, BinEncoder, Restrict},
18};
19
20/// [RFC 1035, DOMAIN NAMES - IMPLEMENTATION AND SPECIFICATION, November 1987](https://tools.ietf.org/html/rfc1035)
21///
22/// ```text
23/// 3.3.10. NULL RDATA format (EXPERIMENTAL)
24///
25///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
26///     /                  <anything>                   /
27///     /                                               /
28///     +--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+--+
29///
30/// Anything at all may be in the RDATA field so long as it is 65535 octets
31/// or less.
32///
33/// NULL records cause no additional section processing.  NULL RRs are not
34/// allowed in Zone Files.  NULLs are used as placeholders in some
35/// experimental extensions of the DNS.
36/// ```
37#[cfg_attr(feature = "serde-config", derive(Deserialize, Serialize))]
38#[derive(Default, Debug, PartialEq, Eq, Hash, Clone)]
39pub struct NULL {
40    anything: Vec<u8>,
41}
42
43impl NULL {
44    /// Construct a new NULL RData
45    pub const fn new() -> Self {
46        Self {
47            anything: Vec::new(),
48        }
49    }
50
51    /// Constructs a new NULL RData with the associated data
52    pub fn with(anything: Vec<u8>) -> Self {
53        // FIXME: we don't want empty data for NULL's, should be Option in the Record
54        debug_assert!(!anything.is_empty());
55
56        Self { anything }
57    }
58
59    /// Returns the buffer stored in the NULL
60    pub fn anything(&self) -> &[u8] {
61        &self.anything
62    }
63}
64
65impl BinEncodable for NULL {
66    fn emit(&self, encoder: &mut BinEncoder<'_>) -> ProtoResult<()> {
67        for b in self.anything() {
68            encoder.emit(*b)?;
69        }
70
71        Ok(())
72    }
73}
74
75impl<'r> RecordDataDecodable<'r> for NULL {
76    fn read_data(decoder: &mut BinDecoder<'r>, length: Restrict<u16>) -> ProtoResult<Self> {
77        let rdata_length = length.map(|u| u as usize).unverified(/*any u16 is valid*/);
78        if rdata_length > 0 {
79            let anything = decoder.read_vec(rdata_length)?.unverified(/*any byte array is good*/);
80            Ok(Self::with(anything))
81        } else {
82            Ok(Self::new())
83        }
84    }
85}
86
87impl RecordData for NULL {
88    fn try_from_rdata(data: RData) -> Result<Self, RData> {
89        match data {
90            RData::NULL(csync) => Ok(csync),
91            _ => Err(data),
92        }
93    }
94
95    fn try_borrow(data: &RData) -> Option<&Self> {
96        match data {
97            RData::NULL(csync) => Some(csync),
98            _ => None,
99        }
100    }
101
102    fn record_type(&self) -> RecordType {
103        RecordType::NULL
104    }
105
106    fn into_rdata(self) -> RData {
107        RData::NULL(self)
108    }
109}
110
111impl fmt::Display for NULL {
112    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
113        f.write_str(&data_encoding::BASE64.encode(&self.anything))
114    }
115}
116
117#[cfg(test)]
118mod tests {
119    #![allow(clippy::dbg_macro, clippy::print_stdout)]
120
121    use super::*;
122
123    #[test]
124    fn test() {
125        let rdata = NULL::with(vec![0, 1, 2, 3, 4, 5, 6, 7]);
126
127        let mut bytes = Vec::new();
128        let mut encoder: BinEncoder<'_> = BinEncoder::new(&mut bytes);
129        assert!(rdata.emit(&mut encoder).is_ok());
130        let bytes = encoder.into_bytes();
131
132        println!("bytes: {bytes:?}");
133
134        let mut decoder: BinDecoder<'_> = BinDecoder::new(bytes);
135        let restrict = Restrict::new(bytes.len() as u16);
136        let read_rdata = NULL::read_data(&mut decoder, restrict).expect("Decoding error");
137        assert_eq!(rdata, read_rdata);
138    }
139}