simple_dns/dns/rdata/
afsdb.rs1use std::collections::HashMap;
2
3use crate::dns::{name::Label, Name, WireFormat};
4
5use super::RR;
6
7#[derive(Debug, PartialEq, Eq, Hash, Clone)]
9pub struct AFSDB<'a> {
10 pub subtype: u16,
12 pub hostname: Name<'a>,
14}
15
16impl<'a> RR for AFSDB<'a> {
17 const TYPE_CODE: u16 = 18;
18}
19
20impl<'a> AFSDB<'a> {
21 pub fn into_owned<'b>(self) -> AFSDB<'b> {
23 AFSDB {
24 subtype: self.subtype,
25 hostname: self.hostname.into_owned(),
26 }
27 }
28}
29
30impl<'a> WireFormat<'a> for AFSDB<'a> {
31 fn parse(data: &'a [u8], position: &mut usize) -> crate::Result<Self>
32 where
33 Self: Sized,
34 {
35 let subtype = u16::from_be_bytes(data[*position..*position + 2].try_into()?);
36 *position += 2;
37 let hostname = Name::parse(data, position)?;
38
39 Ok(Self { subtype, hostname })
40 }
41
42 fn write_to<T: std::io::Write>(&self, out: &mut T) -> crate::Result<()> {
43 out.write_all(&self.subtype.to_be_bytes())?;
44 self.hostname.write_to(out)
45 }
46
47 fn write_compressed_to<T: std::io::Write + std::io::Seek>(
48 &'a self,
49 out: &mut T,
50 name_refs: &mut HashMap<&'a [Label<'a>], usize>,
51 ) -> crate::Result<()> {
52 out.write_all(&self.subtype.to_be_bytes())?;
53 self.hostname.write_compressed_to(out, name_refs)
54 }
55
56 fn len(&self) -> usize {
57 self.hostname.len() + 2
58 }
59}
60
61#[cfg(test)]
62mod tests {
63 use crate::{rdata::RData, ResourceRecord};
64
65 use super::*;
66
67 #[test]
68 fn parse_and_write_afsdb() {
69 let afsdb = AFSDB {
70 subtype: 1,
71 hostname: Name::new("e.hostname.com").unwrap(),
72 };
73
74 let mut data = Vec::new();
75 assert!(afsdb.write_to(&mut data).is_ok());
76
77 let afsdb = AFSDB::parse(&data, &mut 0);
78 assert!(afsdb.is_ok());
79 let afsdb = afsdb.unwrap();
80
81 assert_eq!(data.len(), afsdb.len());
82 assert_eq!(1, afsdb.subtype);
83 assert_eq!("e.hostname.com", afsdb.hostname.to_string());
84 }
85
86 #[test]
87 fn parse_sample() -> Result<(), Box<dyn std::error::Error>> {
88 let sample_file = std::fs::read("samples/zonefile/AFSDB.sample")?;
89
90 let sample_rdata = match ResourceRecord::parse(&sample_file, &mut 0)?.rdata {
91 RData::AFSDB(rdata) => rdata,
92 _ => unreachable!(),
93 };
94
95 assert_eq!(sample_rdata.subtype, 0);
96 assert_eq!(sample_rdata.hostname, "hostname.sample".try_into()?);
97 Ok(())
98 }
99}