1use std::fmt;
4use std::ops::{Deref, DerefMut};
5
6use serde::de::{self, MapAccess, Visitor};
7use serde::ser::SerializeStruct;
8use serde::{Deserialize, Deserializer, Serialize, Serializer};
9
10use crate::Field;
11
12#[derive(Debug, Clone, PartialEq, Eq)]
38pub struct Segment(pub er7::Segment);
39
40impl From<er7::Segment> for Segment {
41 fn from(inner: er7::Segment) -> Segment {
42 Segment(inner)
43 }
44}
45
46impl From<Segment> for er7::Segment {
47 fn from(outer: Segment) -> er7::Segment {
48 outer.0
49 }
50}
51
52impl Deref for Segment {
53 type Target = er7::Segment;
54
55 fn deref(&self) -> &er7::Segment {
56 &self.0
57 }
58}
59
60impl DerefMut for Segment {
61 fn deref_mut(&mut self) -> &mut er7::Segment {
62 &mut self.0
63 }
64}
65
66impl Serialize for Segment {
67 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
68 where
69 S: Serializer,
70 {
71 let fields: Vec<Field> = self.0.fields.iter().map(|f| Field(f.clone())).collect();
72 let mut state = serializer.serialize_struct("Segment", 2)?;
73 state.serialize_field("name", &self.0.name)?;
74 state.serialize_field("fields", &fields)?;
75 state.end()
76 }
77}
78
79const FIELDS: &[&str] = &["name", "fields"];
80
81struct SegmentVisitor;
82
83impl<'de> Visitor<'de> for SegmentVisitor {
84 type Value = Segment;
85
86 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
87 formatter.write_str("a segment object with \"name\" and \"fields\"")
88 }
89
90 fn visit_map<V>(self, mut map: V) -> Result<Segment, V::Error>
91 where
92 V: MapAccess<'de>,
93 {
94 let mut name: Option<String> = None;
95 let mut fields: Option<Vec<Field>> = None;
96
97 while let Some(key) = map.next_key::<String>()? {
98 match key.as_str() {
99 "name" => {
100 if name.is_some() {
101 return Err(de::Error::duplicate_field("name"));
102 }
103 name = Some(map.next_value()?);
104 }
105 "fields" => {
106 if fields.is_some() {
107 return Err(de::Error::duplicate_field("fields"));
108 }
109 fields = Some(map.next_value()?);
110 }
111 _ => {
112 let _ = map.next_value::<de::IgnoredAny>()?;
113 }
114 }
115 }
116
117 let name = name.ok_or_else(|| de::Error::missing_field("name"))?;
118 let fields = fields.ok_or_else(|| de::Error::missing_field("fields"))?;
119 Ok(Segment(er7::Segment {
120 name,
121 fields: fields.into_iter().map(|f| f.0).collect(),
122 }))
123 }
124}
125
126impl<'de> Deserialize<'de> for Segment {
127 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
128 where
129 D: Deserializer<'de>,
130 {
131 deserializer.deserialize_struct("Segment", FIELDS, SegmentVisitor)
132 }
133}
134
135#[cfg(test)]
136mod tests {
137 use super::*;
138
139 #[test]
140 fn round_trips_a_segment() {
141 let segment = Segment(er7::Segment {
142 name: "PID".into(),
143 fields: vec![er7::Field {
144 repetitions: vec![er7::Repetition {
145 components: vec![er7::Component {
146 subcomponents: vec![er7::Subcomponent::new("1")],
147 }],
148 }],
149 }],
150 });
151 let json = serde_json::to_string(&segment).unwrap();
152 let back: Segment = serde_json::from_str(&json).unwrap();
153 assert_eq!(back, segment);
154 }
155
156 #[test]
157 fn rejects_a_missing_name() {
158 let err = serde_json::from_str::<Segment>(r#"{"fields":[]}"#).unwrap_err();
159 assert!(err.to_string().contains("name"));
160 }
161
162 #[test]
163 fn ignores_unknown_fields() {
164 let json = r#"{"name":"ZZZ","fields":[],"extra":true}"#;
165 let back: Segment = serde_json::from_str(json).unwrap();
166 assert_eq!(back.name, "ZZZ");
167 }
168}