dtn7_plus/location/
loc.rs1use core::convert::TryFrom;
2use core::fmt;
3use derive_try_from_primitive::TryFromPrimitive;
4use serde::de::{SeqAccess, Visitor};
5use serde::ser::{SerializeSeq, Serializer};
6use serde::{de, Deserialize, Deserializer, Serialize};
7
8#[derive(Debug, Clone, PartialEq, TryFromPrimitive)]
9#[repr(u8)]
10enum LocationType {
11 LatLon = 1,
12 Human = 2,
13 WFW = 3,
14 XY = 4,
15}
16
17#[derive(Debug, Clone, PartialEq)]
20pub enum Location {
21 LatLon((f32, f32)),
23 Human(String),
25 WFW(String),
27 XY((f32, f32)),
29}
30
31impl Serialize for Location {
32 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
33 where
34 S: Serializer,
35 {
36 let mut seq = serializer.serialize_seq(Some(2))?;
37 match self {
38 Location::LatLon(coords) => {
39 seq.serialize_element(&(LocationType::LatLon as u8))?;
40 seq.serialize_element(&coords)?;
41 }
42 Location::Human(address) => {
43 seq.serialize_element(&(LocationType::Human as u8))?;
44 seq.serialize_element(&address)?;
45 }
46 Location::WFW(address) => {
47 seq.serialize_element(&(LocationType::WFW as u8))?;
48 seq.serialize_element(&address)?;
49 }
50 Location::XY(coords) => {
51 seq.serialize_element(&(LocationType::XY as u8))?;
52 seq.serialize_element(&coords)?;
53 }
54 }
55 seq.end()
56 }
57}
58
59impl<'de> Deserialize<'de> for Location {
60 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
61 where
62 D: Deserializer<'de>,
63 {
64 struct LocationVisitor;
65
66 impl<'de> Visitor<'de> for LocationVisitor {
67 type Value = Location;
68
69 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
70 formatter.write_str("Location")
71 }
72
73 fn visit_seq<V>(self, mut seq: V) -> Result<Self::Value, V::Error>
74 where
75 V: SeqAccess<'de>,
76 {
77 let loc_type: u8 = seq
78 .next_element()?
79 .ok_or_else(|| de::Error::invalid_length(0, &self))?;
80 let loc = LocationType::try_from(loc_type).map_err(|_err| {
81 de::Error::invalid_value(
82 serde::de::Unexpected::Unsigned(loc_type.into()),
83 &self,
84 )
85 })?;
86 match loc {
87 LocationType::LatLon => {
88 let coords: (f32, f32) = seq
89 .next_element()?
90 .ok_or_else(|| de::Error::invalid_length(1, &self))?;
91 Ok(Location::LatLon(coords))
92 }
93 LocationType::Human => {
94 let address: String = seq
95 .next_element()?
96 .ok_or_else(|| de::Error::invalid_length(1, &self))?;
97 Ok(Location::Human(address))
98 }
99 LocationType::WFW => {
100 let address: String = seq
101 .next_element()?
102 .ok_or_else(|| de::Error::invalid_length(1, &self))?;
103 Ok(Location::WFW(address))
104 }
105 LocationType::XY => {
106 let coords: (f32, f32) = seq
107 .next_element()?
108 .ok_or_else(|| de::Error::invalid_length(1, &self))?;
109 Ok(Location::XY(coords))
110 }
111 }
112 }
113 }
114
115 deserializer.deserialize_any(LocationVisitor)
116 }
117}
118
119#[cfg(test)]
120mod tests {
121 use crate::location::Location;
122 #[test]
123 fn test_loc_lonlat_roundtrip() {
124 let loc = Location::LatLon((23.0, 42.0));
125 let buf = serde_cbor::to_vec(&loc).unwrap();
126 let loc2 = serde_cbor::from_slice(&buf).unwrap();
127 assert_eq!(loc, loc2);
128 }
129 #[test]
130 fn test_loc_xy_roundtrip() {
131 let loc = Location::XY((23.0, 42.0));
132 let buf = serde_cbor::to_vec(&loc).unwrap();
133 let loc2 = serde_cbor::from_slice(&buf).unwrap();
134 assert_eq!(loc, loc2);
135 }
136
137 #[test]
138 fn test_loc_human_roundtrip() {
139 let loc = Location::Human("Bahnhofstr 23, 12345 Nirgendwo".into());
140 let buf = serde_cbor::to_vec(&loc).unwrap();
141 let loc2 = serde_cbor::from_slice(&buf).unwrap();
142 assert_eq!(loc, loc2);
143 }
144
145 #[test]
146 fn test_loc_wfw_roundtrip() {
147 let loc = Location::WFW("SINKUT-MEIJER-BETSUKAI".into());
148 let buf = serde_cbor::to_vec(&loc).unwrap();
149 let loc2 = serde_cbor::from_slice(&buf).unwrap();
150 assert_eq!(loc, loc2);
151 }
152}