Skip to main content

tpack_core/native/
collections.rs

1use alloc::{boxed::Box, vec::Vec};
2
3use crate::{Result, Schema, TpackValue};
4
5use super::helpers::{deserialize_via_from_value, list_schema, optional_schema, type_mismatch};
6use super::{FromTpackValue, TpackDeserialize, TpackSerialize};
7
8impl<T> TpackSerialize for Option<T>
9where
10    T: TpackSerialize,
11{
12    fn schema() -> Schema {
13        optional_schema(T::schema())
14    }
15
16    fn to_value(&self) -> TpackValue<'_> {
17        TpackValue::Optional(self.as_ref().map(|value| Box::new(value.to_value())))
18    }
19}
20
21impl<'de, T> TpackDeserialize<'de> for Option<T>
22where
23    T: TpackDeserialize<'de>,
24    Option<T>: FromTpackValue<'de>,
25{
26    fn schema() -> Schema {
27        optional_schema(T::schema())
28    }
29
30    fn from_value(value: TpackValue<'de>) -> Result<Self> {
31        deserialize_via_from_value(value)
32    }
33}
34
35impl<'de, T> FromTpackValue<'de> for Option<T>
36where
37    T: TpackDeserialize<'de>,
38{
39    fn from_value(value: TpackValue<'de>) -> Result<Self> {
40        match value {
41            TpackValue::Optional(None) => Ok(None),
42            TpackValue::Optional(Some(value)) => {
43                Ok(Some(<T as TpackDeserialize<'de>>::from_value(*value)?))
44            }
45            _ => Err(type_mismatch("Optional")),
46        }
47    }
48}
49
50impl<T> TpackSerialize for Vec<T>
51where
52    T: TpackSerialize,
53{
54    fn schema() -> Schema {
55        list_schema(T::schema())
56    }
57
58    fn to_value(&self) -> TpackValue<'_> {
59        TpackValue::List(self.iter().map(TpackSerialize::to_value).collect())
60    }
61}
62
63impl<'de, T> TpackDeserialize<'de> for Vec<T>
64where
65    T: TpackDeserialize<'de>,
66    Vec<T>: FromTpackValue<'de>,
67{
68    fn schema() -> Schema {
69        list_schema(T::schema())
70    }
71
72    fn from_value(value: TpackValue<'de>) -> Result<Self> {
73        deserialize_via_from_value(value)
74    }
75}
76
77impl<'de, T> FromTpackValue<'de> for Vec<T>
78where
79    T: TpackDeserialize<'de>,
80{
81    fn from_value(value: TpackValue<'de>) -> Result<Self> {
82        match value {
83            TpackValue::List(values) => values
84                .into_iter()
85                .map(<T as TpackDeserialize<'de>>::from_value)
86                .collect(),
87            _ => Err(type_mismatch("List")),
88        }
89    }
90}