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