simple_dns/dns/rdata/
eui.rs

1use crate::{bytes_buffer::BytesBuffer, dns::WireFormat, lib::Write};
2
3use super::RR;
4
5/// A 48 bit mac address
6#[derive(Debug, PartialEq, Eq, Hash, Clone)]
7pub struct EUI48 {
8    /// A 48 bit mac address
9    pub address: [u8; 6],
10}
11
12/// A 64 bit mac address
13#[derive(Debug, PartialEq, Eq, Hash, Clone)]
14pub struct EUI64 {
15    /// A 64 bit mac address
16    pub address: [u8; 8],
17}
18
19impl RR for EUI48 {
20    const TYPE_CODE: u16 = 108;
21}
22
23impl RR for EUI64 {
24    const TYPE_CODE: u16 = 109;
25}
26
27impl WireFormat<'_> for EUI48 {
28    const MINIMUM_LEN: usize = 6;
29
30    fn parse(data: &mut BytesBuffer) -> crate::Result<Self>
31    where
32        Self: Sized,
33    {
34        let address = data.get_array()?;
35        Ok(Self { address })
36    }
37
38    fn write_to<T: Write>(&self, out: &mut T) -> crate::Result<()> {
39        out.write_all(&self.address)
40    }
41}
42
43impl WireFormat<'_> for EUI64 {
44    const MINIMUM_LEN: usize = 8;
45
46    fn parse(data: &mut BytesBuffer) -> crate::Result<Self>
47    where
48        Self: Sized,
49    {
50        let address = data.get_array()?;
51        Ok(Self { address })
52    }
53
54    fn write_to<T: Write>(&self, out: &mut T) -> crate::Result<()> {
55        out.write_all(&self.address)
56    }
57}
58
59impl EUI48 {
60    /// Transforms the inner data into its owned type
61    pub fn into_owned(self) -> Self {
62        self
63    }
64}
65
66impl EUI64 {
67    /// Transforms the inner data into its owned type
68    pub fn into_owned(self) -> Self {
69        self
70    }
71}
72
73impl From<EUI48> for [u8; 6] {
74    fn from(value: EUI48) -> Self {
75        value.address
76    }
77}
78
79impl From<EUI64> for [u8; 8] {
80    fn from(value: EUI64) -> Self {
81        value.address
82    }
83}
84
85#[cfg(test)]
86mod tests {
87    use crate::lib::Vec;
88    #[cfg(feature = "std")]
89    use crate::{rdata::RData, ResourceRecord};
90
91    use super::*;
92
93    #[test]
94    fn parse_and_write_eui48() {
95        let mac = [0, 0, 0, 0, 0, 0];
96        let rdata = EUI48 { address: mac };
97        let mut writer = Vec::new();
98        rdata.write_to(&mut writer).unwrap();
99        let rdata = EUI48::parse(&mut BytesBuffer::new(&writer)).unwrap();
100        assert_eq!(rdata.address, mac);
101    }
102
103    #[test]
104    fn parse_and_write_eui64() {
105        let mac = [0, 0, 0, 0, 0, 0, 0, 0];
106        let rdata = EUI64 { address: mac };
107        let mut writer = Vec::new();
108        rdata.write_to(&mut writer).unwrap();
109        let rdata = EUI64::parse(&mut (&writer[..]).into()).unwrap();
110        assert_eq!(rdata.address, mac);
111    }
112
113    #[test]
114    #[cfg(feature = "std")]
115    fn parse_sample_eui48() -> Result<(), Box<dyn std::error::Error>> {
116        let sample_file = std::fs::read("samples/zonefile/EUI48.sample")?;
117
118        let sample_rdata = match ResourceRecord::parse(&mut (&sample_file[..]).into())?.rdata {
119            RData::EUI48(rdata) => rdata,
120            _ => unreachable!(),
121        };
122
123        assert_eq!(sample_rdata.address, [0x00, 0x00, 0x5e, 0x00, 0x53, 0x2a]);
124
125        Ok(())
126    }
127
128    #[test]
129    #[cfg(feature = "std")]
130    fn parse_sample_eui64() -> Result<(), Box<dyn std::error::Error>> {
131        let sample_file = std::fs::read("samples/zonefile/EUI64.sample")?;
132
133        let sample_rdata = match ResourceRecord::parse(&mut (&sample_file[..]).into())?.rdata {
134            RData::EUI64(rdata) => rdata,
135            _ => unreachable!(),
136        };
137
138        assert_eq!(
139            sample_rdata.address,
140            [0x00, 0x00, 0x5e, 0xef, 0x10, 0x00, 0x00, 0x2a]
141        );
142
143        Ok(())
144    }
145}