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#[derive(Copy, Clone, Debug, PartialEq)]
10pub struct Apl<'a> {
11 pub address_family: u8,
13 pub prefix: u8,
15 pub negation: bool,
17 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, 0x02, 0x03, 0x01, 0x02, 0x03, ],
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, 0x02, 0x83, 0x01, 0x02, 0x03, ],
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}