1use serde::de;
2use serde::ser;
3
4use std::str::FromStr;
5use std::{fmt, vec};
6
7#[derive(Debug, Clone, PartialEq, Eq)]
8pub struct CS<T>(pub Vec<T>);
9
10impl<T> Default for CS<T> {
11 #[inline]
12 fn default() -> Self {
13 Self(Default::default())
14 }
15}
16
17impl<T> AsRef<[T]> for CS<T> {
18 #[inline]
19 fn as_ref(&self) -> &[T] {
20 &self.0
21 }
22}
23
24impl<T> From<Vec<T>> for CS<T> {
25 #[inline]
26 fn from(v: Vec<T>) -> Self {
27 Self(v)
28 }
29}
30
31impl<T> CS<T> {
32 #[inline]
33 pub fn into_inner(self) -> Vec<T> {
34 self.0
35 }
36
37 #[inline]
38 pub fn to_inner(&self) -> &Vec<T> {
39 &self.0
40 }
41
42 #[inline]
43 pub fn to_inner_mut(&mut self) -> &mut Vec<T> {
44 &mut self.0
45 }
46}
47
48impl<T: FromStr> FromStr for CS<T> {
49 type Err = T::Err;
50
51 fn from_str(s: &str) -> Result<Self, Self::Err> {
52 s.split(',')
53 .filter(|s| !s.is_empty())
54 .map(T::from_str)
55 .collect::<Result<Vec<_>, _>>()
56 .map(Self)
57 }
58}
59
60impl<T> IntoIterator for CS<T> {
61 type Item = T;
62 type IntoIter = vec::IntoIter<T>;
63
64 fn into_iter(self) -> Self::IntoIter {
65 self.0.into_iter()
66 }
67}
68
69impl<T: fmt::Display> fmt::Display for CS<T> {
70 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
71 let mut it = self.0.iter();
72 if let Some(v) = it.next() {
73 <T as fmt::Display>::fmt(v, f)?;
74 }
75
76 for v in it {
77 write!(f, ",{}", v)?
78 }
79
80 Ok(())
81 }
82}
83
84impl<T: fmt::Display> ser::Serialize for CS<T> {
85 fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
86 where
87 S: ser::Serializer,
88 {
89 serializer.serialize_str(&self.to_string())
90 }
91}
92
93impl<'de, T> de::Deserialize<'de> for CS<T>
94where
95 T: FromStr,
96 T::Err: fmt::Display,
97{
98 fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
99 where
100 D: de::Deserializer<'de>,
101 {
102 use std::marker::PhantomData;
103
104 struct CsVisitor<T>(PhantomData<T>);
105
106 impl<'de, T> de::Visitor<'de> for CsVisitor<T>
107 where
108 T: FromStr,
109 T::Err: fmt::Display,
110 {
111 type Value = CS<T>;
112
113 fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
114 formatter.write_str("comma separeted list")
115 }
116
117 fn visit_str<E>(self, values: &str) -> Result<Self::Value, E>
118 where
119 E: de::Error,
120 {
121 values.parse().map_err(de::Error::custom)
122 }
123 }
124
125 deserializer.deserialize_str(CsVisitor(PhantomData))
126 }
127}
128
129#[cfg(test)]
130mod tests {
131 use super::CS;
132 type CsTest = CS<u32>;
133
134 fn assert_ok_from_str(s: &str, expected: Vec<u32>) {
135 let cs: Result<CsTest, _> = s.parse();
136 assert!(matches!(cs, Ok(v) if v == CS(expected)))
137 }
138
139 fn assert_err_from_str(s: &str) {
140 let cs: Result<CsTest, _> = s.parse();
141 assert!(cs.is_err())
142 }
143
144 #[test]
145 fn from_str() {
146 assert_ok_from_str("", vec![]);
147 assert_ok_from_str(",,,,", vec![]);
148
149 assert_ok_from_str("1", vec![1]);
150 assert_ok_from_str(",1", vec![1]);
151 assert_ok_from_str("1,", vec![1]);
152 assert_ok_from_str(",,,1,", vec![1]);
153
154 assert_ok_from_str("1,2", vec![1, 2]);
155 assert_ok_from_str("1,2,3,4,5", vec![1, 2, 3, 4, 5]);
156 assert_ok_from_str("1,,,,,2", vec![1, 2]);
157 assert_ok_from_str(",,,1,,,,,2,,,,,", vec![1, 2]);
158
159 assert_err_from_str("-1");
160 assert_err_from_str("1,a,");
161 }
162
163 fn assert_to_string(values: Vec<u32>, expected: &str) {
164 let cs = CS(values).to_string();
165 assert_eq!(cs, expected);
166 }
167
168 #[test]
169 fn to_string() {
170 assert_to_string(vec![], "");
171 assert_to_string(vec![1], "1");
172 assert_to_string(vec![1, 2], "1,2");
173 assert_to_string(vec![1, 2, 3, 4, 5], "1,2,3,4,5");
174 }
175
176 fn assert_ok_des(s: &str, expected: Vec<u32>) {
177 let cs: Result<CsTest, _> = serde_json::from_str(s);
178 assert!(matches!(cs, Ok(v) if v == CS(expected)))
179 }
180
181 fn assert_err_des(s: &str) {
182 let cs: Result<CsTest, _> = serde_json::from_str(s);
183 assert!(cs.is_err())
184 }
185
186 #[test]
187 fn deserialize() {
188 assert_ok_des(r#""""#, vec![]);
189 assert_ok_des(r#"",,,,""#, vec![]);
190
191 assert_ok_des(r#""1""#, vec![1]);
192 assert_ok_des(r#"",1""#, vec![1]);
193 assert_ok_des(r#""1,""#, vec![1]);
194 assert_ok_des(r#"",,,1,""#, vec![1]);
195
196 assert_ok_des(r#""1,2""#, vec![1, 2]);
197 assert_ok_des(r#""1,2,3,4,5""#, vec![1, 2, 3, 4, 5]);
198 assert_ok_des(r#""1,,,,,2""#, vec![1, 2]);
199 assert_ok_des(r#"",,,1,,,,,2,,,,,""#, vec![1, 2]);
200
201 assert_err_des(r#""-1""#);
202 assert_err_des(r#""1,a,""#);
203 }
204
205 fn assert_ser(values: Vec<u32>, expected: &str) {
206 let cs = serde_json::to_string(&CS(values));
207 assert!(matches!(cs, Ok(v) if v == expected))
208 }
209
210 #[test]
211 fn serialize() {
212 assert_ser(vec![], r#""""#);
213 assert_ser(vec![1], r#""1""#);
214 assert_ser(vec![1, 2], r#""1,2""#);
215 assert_ser(vec![1, 2, 3, 4, 5], r#""1,2,3,4,5""#);
216 }
217}