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