1use crate::{
2 ds::{InvalidFieldName, InvalidId},
3 Kserd, Value,
4};
5use std::{error, fmt};
6
7pub trait ToKserd<'a> {
87 fn into_kserd(self) -> Result<Kserd<'a>, ToKserdErr>;
89}
90
91#[derive(Debug, PartialEq, Clone)]
93pub enum ToKserdErr {
94 InvalidId(InvalidId),
96 InvalidFieldName(InvalidFieldName),
98}
99
100impl error::Error for ToKserdErr {}
101
102impl fmt::Display for ToKserdErr {
103 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
104 match self {
105 ToKserdErr::InvalidId(s) => write!(f, "{}", s),
106 ToKserdErr::InvalidFieldName(s) => write!(f, "{}", s),
107 }
108 }
109}
110
111impl<'a> ToKserd<'a> for Kserd<'a> {
112 fn into_kserd(self) -> Result<Kserd<'a>, ToKserdErr> {
113 Ok(self)
114 }
115}
116
117impl From<InvalidId> for ToKserdErr {
118 fn from(id: InvalidId) -> ToKserdErr {
119 ToKserdErr::InvalidId(id)
120 }
121}
122
123impl From<InvalidFieldName> for ToKserdErr {
124 fn from(x: InvalidFieldName) -> ToKserdErr {
125 ToKserdErr::InvalidFieldName(x)
126 }
127}
128
129#[cfg(test)]
130use rand::{random, thread_rng, Rng};
131#[cfg(test)]
132fn random_string() -> String {
133 let mut rng = rand::thread_rng();
134 let len = rng.gen::<u8>() as usize;
135 let mut s = String::new();
136 for _ in 0..len {
137 s.push(rng.gen());
138 }
139 s
140}
141
142#[test]
143fn test_kserd_to_kserd() {
144 let kserd = (random_string(), rand::random::<usize>())
145 .into_kserd()
146 .unwrap();
147 let kserdnew = kserd.clone().into_kserd().unwrap();
148 assert_eq!(kserd, kserdnew);
149}
150
151#[test]
152fn test_tokserderr_display() {
153 let e: ToKserdErr = Kserd::with_id(".", Value::Unit).unwrap_err().into();
154 assert_eq!(
155 &e.to_string(),
156 r#"identity '.' contains invalid characters. Invalid characters: '(){}[]<> ,./\='"#
157 );
158
159 let e: ToKserdErr = Value::new_cntr(vec![("/", Kserd::new_unit())])
160 .unwrap_err()
161 .into();
162 assert_eq!(
163 &e.to_string(),
164 r#"invalid field name: invalid character '/' exists in name '/'"#
165 );
166}
167
168macro_rules! number {
171 ( $( $x:ty ) * ) => {
172 $(
173 impl ToKserd<'static> for $x {
174 fn into_kserd(self) -> Result<Kserd<'static>, ToKserdErr> {
175 Ok(Kserd::new_num(self))
176 }
177 }
178 )*
179 }
180}
181
182number!(
183 usize u8 u16 u32 u64 u128
184 isize i8 i16 i32 i64 i128
185 f32 f64
186);
187
188impl ToKserd<'static> for () {
189 fn into_kserd(self) -> Result<Kserd<'static>, ToKserdErr> {
190 Ok(Kserd::new_unit())
191 }
192}
193
194impl ToKserd<'static> for bool {
195 fn into_kserd(self) -> Result<Kserd<'static>, ToKserdErr> {
196 Ok(Kserd::new_bool(self))
197 }
198}
199
200impl ToKserd<'static> for char {
201 fn into_kserd(self) -> Result<Kserd<'static>, ToKserdErr> {
202 Ok(Kserd::with_id_unchk(
203 "char",
204 Value::Str(self.to_string().into()),
205 ))
206 }
207}
208
209#[test]
210fn test_copyable_primitives() {
211 assert_eq!(123_456.into_kserd(), Ok(Kserd::new_num(123_456)));
212 assert_eq!((-1_234_567).into_kserd(), Ok(Kserd::new_num(-1_234_567)));
213 assert_eq!(3.14.into_kserd(), Ok(Kserd::new_num(3.14)));
214 assert_eq!(().into_kserd(), Ok(Kserd::new_unit()));
215 assert_eq!(true.into_kserd(), Ok(Kserd::new_bool(true)));
216 assert_eq!('y'.into_kserd(), Ok(Kserd::new_str("y")));
217}
218
219impl ToKserd<'static> for String {
222 fn into_kserd(self) -> Result<Kserd<'static>, ToKserdErr> {
223 Ok(Kserd::new_string(self))
224 }
225}
226
227impl<'a> ToKserd<'a> for &'a str {
228 fn into_kserd(self) -> Result<Kserd<'a>, ToKserdErr> {
229 Ok(Kserd::new_str(self))
230 }
231}
232
233#[test]
234fn test_strings() {
235 let s = random_string();
236 assert_eq!(s.as_str().into_kserd(), Ok(Kserd::new_str(&s)));
237 assert_eq!(s.clone().into_kserd(), Ok(Kserd::new_string(s)));
238}
239
240macro_rules! tuples {
243 ( $( $lifetime:tt|$element:tt|$idx:tt ),+ ) => {
244 impl<'kserd, $($lifetime: 'kserd,)* $($element,)*> ToKserd<'kserd> for ($($element,)*)
245 where
246 $(
247 $element: ToKserd<$lifetime>,
248 )*
249 {
250 fn into_kserd(self) -> Result<Kserd<'kserd>, ToKserdErr> {
251 let v = vec![$(
252 self.$idx.into_kserd()?,
253 )*];
254 Ok(Kserd::new(Value::Tuple(v)))
255 }
256 }
257 }
258}
259
260tuples!('a|A|0);
261tuples!('a|A|0,'b|B|1);
262tuples!('a|A|0,'b|B|1,'c|C|2);
263tuples!('a|A|0,'b|B|1,'c|C|2, 'd|D|3);
264tuples!('a|A|0,'b|B|1,'c|C|2, 'd|D|3, 'e|E|4);
265tuples!('a|A|0,'b|B|1,'c|C|2, 'd|D|3, 'e|E|4, 'f|F|5);
266tuples!('a|A|0,'b|B|1,'c|C|2, 'd|D|3, 'e|E|4, 'f|F|5, 'g|G|6);
267tuples!('a|A|0,'b|B|1,'c|C|2, 'd|D|3, 'e|E|4, 'f|F|5, 'g|G|6, 'h|H|7);
268tuples!('a|A|0,'b|B|1,'c|C|2, 'd|D|3, 'e|E|4, 'f|F|5, 'g|G|6, 'h|H|7, 'i|I|8);
269tuples!('a|A|0,'b|B|1,'c|C|2, 'd|D|3, 'e|E|4, 'f|F|5, 'g|G|6, 'h|H|7, 'i|I|8, 'j|J|9);
270tuples!('a|A|0,'b|B|1,'c|C|2, 'd|D|3, 'e|E|4, 'f|F|5, 'g|G|6, 'h|H|7, 'i|I|8, 'j|J|9, 'k|K|10);
271tuples!('a|A|0,'b|B|1,'c|C|2, 'd|D|3, 'e|E|4, 'f|F|5, 'g|G|6, 'h|H|7, 'i|I|8, 'j|J|9, 'k|K|10, 'l|L|11);
272
273macro_rules! array {
274 ( $( $x:literal ) * ) => {
275 $(
276 impl<'a, T: ToKserd<'a>> ToKserd<'a> for [T; $x] {
277 fn into_kserd(self) -> Result<Kserd<'a>, ToKserdErr> {
278 let b: Box<[T]> = Box::new(self);
279 let arr = b.into_vec();
280 let mut v = Vec::with_capacity(arr.len());
281 for i in arr.into_iter() {
282 v.push(i.into_kserd()?);
283 }
284 Ok(Kserd::with_id_unchk("array", Value::Seq(v)))
285 }
286 }
287 )*
288 }
289}
290
291array!(
292 1 2 3 4 5 6 7 8
293 9 10 11 12 13 14 15 16
294 17 18 19 20 21 22 23 24
295 25 26 27 28 29 30 31 32
296);
297
298#[test]
299fn tuples_and_array_test() {
300 let mut rng = thread_rng();
301
302 macro_rules! tester {
303 (arrays $( $size:literal ) * ) => {{
304 $(
305 let mut arr = [0u8; $size];
306 rng.fill(&mut arr[..]);
307 let v = arr.iter().copied().collect::<Vec<_>>();
308 assert_eq!(arr.into_kserd(), v.into_kserd());
309 )*
310 }};
311 (tuples $tuple:expr => $($idx:tt),*) => {{
312 let tuple = $tuple;
313 let kserd = tuple.clone().into_kserd().unwrap();
314 let vec = match kserd.val {
315 Value::Tuple(v) => v,
316 _ => unreachable!("should be a tuple")
317 };
318 $(
319 assert_eq!(tuple.$idx.clone().into_kserd().unwrap(), vec[$idx]);
320 )*
321 }}
322 };
323
324 tester!(arrays
325 1 2 3 4 5 6 7 8
326 9 10 11 12 13 14 15 16
327 17 18 19 20 21 22 23 24
328 25 26 27 28 29 30 31 32
329 );
330
331 tester!(tuples (random_string(),) => 0);
332 tester!(tuples (random_string(), rng.gen::<usize>()) => 0,1);
333 tester!(tuples (random_string(), rng.gen::<usize>(), random_string()) => 0,1,2);
334 tester!(tuples (random_string(), rng.gen::<usize>(), random_string(), rng.gen::<char>()) => 0,1,2,3);
335 tester!(tuples (random_string(), rng.gen::<usize>(), random_string(), rng.gen::<char>(), random_string()) => 0,1,2,3,4);
336 tester!(tuples (random_string(), rng.gen::<usize>(), random_string(), rng.gen::<char>(), random_string(), random_string()) => 0,1,2,3,4,5);
337 tester!(tuples (random_string(), rng.gen::<usize>(), random_string(), rng.gen::<char>(), random_string(), random_string(), rng.gen::<isize>()) => 0,1,2,3,4,5,6);
338 tester!(tuples (random_string(), random::<usize>(), random_string(), rng.gen::<char>(), random_string(), random_string(), rng.gen::<isize>(), rng.gen::<bool>()) => 0,1,2,3,4,5,6,7);
339 tester!(tuples (random_string(), rng.gen::<usize>(), random_string(), rng.gen::<char>(), random_string(), random_string(), rng.gen::<isize>(), rng.gen::<bool>(), rng.gen::<char>()) => 0,1,2,3,4,5,6,7,8);
340 tester!(tuples (random_string(), rng.gen::<usize>(), random_string(), rng.gen::<char>(), random_string(), random_string(), rng.gen::<isize>(), rng.gen::<bool>(), rng.gen::<char>(), rng.gen::<f64>()) => 0,1,2,3,4,5,6,7,8,9);
341 tester!(tuples (random_string(), rng.gen::<usize>(), random_string(), rng.gen::<char>(), random_string(), random_string(), rng.gen::<isize>(), rng.gen::<bool>(), rng.gen::<char>(), rng.gen::<f64>(), random_string()) => 0,1,2,3,4,5,6,7,8,9,10);
342 tester!(tuples (random_string(), rng.gen::<usize>(), random_string(), rng.gen::<char>(), random_string(), random_string(), rng.gen::<isize>(), rng.gen::<bool>(), rng.gen::<char>(), rng.gen::<f64>(), random_string(), random_string()) => 0,1,2,3,4,5,6,7,8,9,10,11);
343}
344
345impl<'a, T: ToKserd<'a>> ToKserd<'a> for Vec<T> {
348 fn into_kserd(self) -> Result<Kserd<'a>, ToKserdErr> {
349 let mut v = Vec::with_capacity(self.len());
350 for i in self {
351 v.push(i.into_kserd()?);
352 }
353 Ok(Kserd::with_id_unchk("Vec", Value::Seq(v)))
354 }
355}
356
357impl<'a, T> ToKserd<'a> for Box<T>
360where
361 T: ToKserd<'a>,
362{
363 fn into_kserd(self) -> Result<Kserd<'a>, ToKserdErr> {
364 (*self).into_kserd()
365 }
366}
367
368impl<'a, T> ToKserd<'a> for Option<T>
381where
382 T: ToKserd<'a>,
383{
384 fn into_kserd(self) -> Result<Kserd<'a>, ToKserdErr> {
385 match self {
386 Some(x) => x.into_kserd(),
387 None => Ok(Kserd::with_id_unchk("None", Value::Tuple(Vec::new()))),
388 }
389 }
390}
391
392impl<'kserd, 't: 'kserd, 'e: 'kserd, T, E> ToKserd<'kserd> for Result<T, E>
393where
394 T: ToKserd<'t>,
395 E: ToKserd<'e>,
396{
397 fn into_kserd(self) -> Result<Kserd<'kserd>, ToKserdErr> {
398 Ok(match self {
399 Ok(x) => Kserd::with_id_unchk("Ok", Value::Tuple(vec![x.into_kserd()?])),
400 Err(x) => Kserd::with_id_unchk("Err", Value::Tuple(vec![x.into_kserd()?])),
401 })
402 }
403}
404
405#[test]
406fn blanket_impls_tests() {
407 let boxed = Box::new(String::from("Hello, world!"));
408 assert_eq!(boxed.into_kserd(), Ok(Kserd::new_str("Hello, world!")));
409
410 let option = Some(String::from("Hello, world!"));
411 assert_eq!(option.into_kserd(), Ok(Kserd::new_str("Hello, world!")));
412 let option: Option<String> = None;
413 assert_eq!(
414 option.into_kserd(),
415 Kserd::with_id("None", Value::Tuple(vec![])).map_err(From::from)
416 );
417
418 let ok: Result<String, String> = Ok(String::from("I am okay!"));
419 assert_eq!(
420 ok.into_kserd(),
421 Ok(Kserd::new(Value::Tuple(vec![Kserd::new_str("I am okay!")])))
422 );
423 let err: Result<String, String> = Err(String::from("I am not!"));
424 assert_eq!(
425 err.into_kserd(),
426 Ok(Kserd::new(Value::Tuple(vec![Kserd::new_str("I am not!")])))
427 );
428}
429
430