simple_dns/dns/rdata/
loc.rs1use crate::{bytes_buffer::BytesBuffer, dns::WireFormat, lib::Write, SimpleDnsError};
2
3use super::RR;
4
5#[derive(Debug, PartialEq, Eq, Hash, Clone)]
7pub struct LOC {
8 pub version: u8,
10 pub size: u8,
12 pub horizontal_precision: u8,
14 pub vertical_precision: u8,
16 pub latitude: i32,
18 pub longitude: i32,
20 pub altitude: i32,
22}
23
24impl RR for LOC {
25 const TYPE_CODE: u16 = 29;
26}
27
28impl LOC {
29 pub fn into_owned(self) -> Self {
31 self
32 }
33}
34
35impl<'a> WireFormat<'a> for LOC {
36 const MINIMUM_LEN: usize = 16;
37
38 fn parse(data: &mut BytesBuffer<'a>) -> crate::Result<Self>
39 where
40 Self: Sized,
41 {
42 let version = data.get_u8()?;
43 if version != 0 {
44 return Err(SimpleDnsError::InvalidDnsPacket);
45 }
46
47 let size = data.get_u8()?;
48 let horizontal_precision = data.get_u8()?;
49 let vertical_precision = data.get_u8()?;
50 let latitude = data.get_i32()?;
51 let longitude = data.get_i32()?;
52 let altitude = data.get_i32()?;
53
54 Ok(LOC {
55 version,
56 size,
57 horizontal_precision,
58 vertical_precision,
59 latitude,
60 longitude,
61 altitude,
62 })
63 }
64
65 fn write_to<T: Write>(&self, out: &mut T) -> crate::Result<()> {
66 if self.version != 0 {
67 return Err(SimpleDnsError::InvalidDnsPacket);
68 }
69
70 out.write_all(&[
71 self.version.to_be(),
72 self.size.to_be(),
73 self.horizontal_precision.to_be(),
74 self.vertical_precision.to_be(),
75 ])?;
76 out.write_all(&self.latitude.to_be_bytes())?;
77 out.write_all(&self.longitude.to_be_bytes())?;
78 out.write_all(&self.altitude.to_be_bytes())?;
79
80 Ok(())
81 }
82}
83
84#[cfg(test)]
85mod tests {
86 use super::*;
87 use crate::lib::Vec;
88
89 #[test]
90 fn parse_and_write_loc() {
91 let loc = LOC {
92 version: 0,
93 size: 0x10,
94 vertical_precision: 0x11,
95 horizontal_precision: 0x12,
96 altitude: 1000,
97 longitude: 2000,
98 latitude: 3000,
99 };
100
101 let mut data = Vec::new();
102 assert!(loc.write_to(&mut data).is_ok());
103
104 let loc = LOC::parse(&mut (&data[..]).into());
105 assert!(loc.is_ok());
106 let loc = loc.unwrap();
107
108 assert_eq!(0x10, loc.size);
109 assert_eq!(0x11, loc.vertical_precision);
110 assert_eq!(0x12, loc.horizontal_precision);
111 assert_eq!(1000, loc.altitude);
112 assert_eq!(2000, loc.longitude);
113 assert_eq!(3000, loc.latitude);
114
115 assert_eq!(data.len(), loc.len());
116 }
117
118 #[test]
119 #[cfg(feature = "std")]
120 fn parse_sample() -> Result<(), Box<dyn std::error::Error>> {
121 use crate::{rdata::RData, ResourceRecord};
122 let sample_file = std::fs::read("samples/zonefile/LOC.sample")?;
123
124 let sample_rdata = match ResourceRecord::parse(&mut (&sample_file[..]).into())?.rdata {
125 RData::LOC(rdata) => rdata,
126 _ => unreachable!(),
127 };
128
129 assert_eq!(35, sample_rdata.size);
131 assert_eq!(35, sample_rdata.vertical_precision);
132 assert_eq!(37, sample_rdata.horizontal_precision);
133 assert_eq!(10001000, sample_rdata.altitude);
134 assert_eq!(-2058743648, sample_rdata.longitude);
135 assert_eq!(-1930943648, sample_rdata.latitude);
136 Ok(())
137 }
138}