1use std::fmt;
4use std::ops::{Deref, DerefMut};
5
6use serde::de::{SeqAccess, Visitor};
7use serde::ser::SerializeSeq;
8use serde::{Deserialize, Deserializer, Serialize, Serializer};
9
10use crate::Subcomponent;
11
12#[derive(Debug, Clone, PartialEq, Eq, Default)]
44pub struct Component(pub er7::Component);
45
46impl From<er7::Component> for Component {
47 fn from(inner: er7::Component) -> Component {
48 Component(inner)
49 }
50}
51
52impl From<Component> for er7::Component {
53 fn from(outer: Component) -> er7::Component {
54 outer.0
55 }
56}
57
58impl Deref for Component {
59 type Target = er7::Component;
60
61 fn deref(&self) -> &er7::Component {
62 &self.0
63 }
64}
65
66impl DerefMut for Component {
67 fn deref_mut(&mut self) -> &mut er7::Component {
68 &mut self.0
69 }
70}
71
72impl Serialize for Component {
73 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
80 where
81 S: Serializer,
82 {
83 let subcomponents = &self.0.subcomponents;
84 let mut seq = serializer.serialize_seq(Some(subcomponents.len()))?;
85 for subcomponent in subcomponents {
86 seq.serialize_element(&Subcomponent(subcomponent.clone()))?;
87 }
88 seq.end()
89 }
90}
91
92struct ComponentVisitor;
93
94impl<'de> Visitor<'de> for ComponentVisitor {
95 type Value = Component;
96
97 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
98 formatter.write_str("an array of subcomponent strings")
99 }
100
101 fn visit_seq<A>(self, mut seq: A) -> Result<Component, A::Error>
102 where
103 A: SeqAccess<'de>,
104 {
105 let mut subcomponents = Vec::with_capacity(seq.size_hint().unwrap_or(0));
106 while let Some(subcomponent) = seq.next_element::<Subcomponent>()? {
107 subcomponents.push(subcomponent.0);
108 }
109 Ok(Component(er7::Component { subcomponents }))
110 }
111}
112
113impl<'de> Deserialize<'de> for Component {
114 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
116 where
117 D: Deserializer<'de>,
118 {
119 deserializer.deserialize_seq(ComponentVisitor)
120 }
121}
122
123#[cfg(test)]
124mod tests {
125 use super::*;
126
127 #[test]
128 fn round_trips_several_subcomponents() {
129 let component = Component(er7::Component {
130 subcomponents: vec![
131 er7::Subcomponent::new("ACME"),
132 er7::Subcomponent::new("1.2.3"),
133 er7::Subcomponent::new("ISO"),
134 ],
135 });
136 let json = serde_json::to_string(&component).unwrap();
137 assert_eq!(json, r#"["ACME","1.2.3","ISO"]"#);
138 let back: Component = serde_json::from_str(&json).unwrap();
139 assert_eq!(back, component);
140 }
141
142 #[test]
143 fn round_trips_an_empty_array() {
144 let component = Component::default();
145 let json = serde_json::to_string(&component).unwrap();
146 assert_eq!(json, "[]");
147 let back: Component = serde_json::from_str(&json).unwrap();
148 assert!(back.subcomponents.is_empty());
149 }
150}