Skip to main content

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