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