flex_dns/rdata/
apl.rs

1use crate::{Buffer, DnsError, DnsMessage, DnsMessageError, MutBuffer};
2use crate::characters::Characters;
3use crate::parse::{Parse, ParseData};
4use crate::rdata::{RData, RDataParse};
5use crate::write::WriteBytes;
6
7/// # Address prefix list record
8/// This record is used to store a list of address prefixes.
9#[derive(Copy, Clone, Debug, PartialEq)]
10pub struct Apl<'a> {
11    /// The address family for the prefix.
12    pub address_family: u8,
13    /// The prefix length.
14    pub prefix: u8,
15    /// The negation flag.
16    pub negation: bool,
17    /// The address family specific data.
18    pub data: Characters<'a>,
19}
20
21impl<'a> RDataParse<'a> for Apl<'a> {
22    #[inline]
23    fn parse(rdata: &RData<'a>, i: &mut usize) -> Result<Self, DnsMessageError> {
24        let bytes = rdata.parse_data();
25        let address_family = u8::parse(rdata.buffer, i)?;
26        let prefix = u8::parse(rdata.buffer, i)?;
27        let length = u8::parse(rdata.buffer, i)?;
28        let negation = length & 0x80 != 0;
29        let length = length & 0x7F;
30
31        if bytes.len() < *i + length as usize {
32            return Err(DnsMessageError::DnsError(DnsError::UnexpectedEndOfBuffer));
33        }
34
35        let data = unsafe {
36            Characters::new_unchecked(&rdata.buffer[*i - 1..*i + length as usize])
37        };
38
39        Ok(Self {
40            address_family,
41            prefix,
42            negation,
43            data,
44        })
45    }
46}
47
48impl<'a> WriteBytes for Apl<'a> {
49    #[inline]
50    fn write<
51        const PTR_STORAGE: usize,
52        const DNS_SECTION: usize,
53        B: MutBuffer + Buffer,
54    >(&self, message: &mut DnsMessage<PTR_STORAGE, DNS_SECTION, B>) -> Result<usize, DnsMessageError> {
55        let mut bytes = 0;
56
57        bytes += self.address_family.write(message)?;
58        bytes += self.prefix.write(message)?;
59
60        let mut length = self.data.as_ref().len() as u8;
61        if self.negation {
62            length |= 0x80;
63        }
64
65        bytes += length.write(message)?;
66        bytes += message.write_bytes(self.data.as_ref())?;
67
68        Ok(bytes)
69    }
70}
71
72#[cfg(test)]
73mod test {
74    use crate::rdata::testutils::parse_write_test;
75
76    use super::*;
77
78    parse_write_test!(
79        6,
80        [
81            0x01, // address family
82            0x02, // prefix
83            0x03, // length
84            0x01, 0x02, 0x03, // data
85        ],
86        Apl {
87            address_family: 0x01,
88            prefix: 0x02,
89            negation: false,
90            data: unsafe { Characters::new_unchecked(&[0x03, 0x01, 0x02, 0x03]) },
91        }
92    );
93    parse_write_test!(
94        6,
95        [
96            0x01, // address family
97            0x02, // prefix
98            0x83, // length
99            0x01, 0x02, 0x03, // data
100        ],
101        Apl {
102            address_family: 0x01,
103            prefix: 0x02,
104            negation: true,
105            data: unsafe { Characters::new_unchecked(&[0x83, 0x01, 0x02, 0x03]) },
106        },
107        parse_negation,
108        write_negation,
109    );
110}