Skip to main content

dw_models/
tryvec.rs

1use core::marker::PhantomData;
2use schemars::{gen::SchemaGenerator, schema::Schema, JsonSchema};
3use serde::de::{DeserializeOwned, SeqAccess, Visitor};
4use serde::ser::SerializeSeq;
5use serde::{Deserialize, Deserializer, Serialize, Serializer};
6use serde_json::Value;
7use std::fmt;
8use std::fmt::Debug;
9
10#[derive(Debug, Clone)]
11pub enum TryParse<T: JsonSchema> {
12    Parsed(T),
13    Unparsed(Value),
14    NotPresent,
15}
16
17impl<T: JsonSchema> JsonSchema for TryParse<T> {
18    fn schema_name() -> String {
19        format!("Try<{}>", std::any::type_name::<T>())
20    }
21
22    fn json_schema(gen: &mut SchemaGenerator) -> Schema {
23        gen.subschema_for::<T>()
24    }
25}
26
27impl<'de, T: DeserializeOwned + JsonSchema> Deserialize<'de> for TryParse<T> {
28    fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
29        match Option::<Value>::deserialize(deserializer)? {
30            None => Ok(TryParse::NotPresent),
31            Some(value) => match T::deserialize(&value) {
32                Ok(t) => Ok(TryParse::Parsed(t)),
33                Err(_) => Ok(TryParse::Unparsed(value)),
34            },
35        }
36    }
37}
38
39#[derive(Debug, Clone, JsonSchema)]
40#[serde(transparent)]
41pub struct TryVec<T: JsonSchema> {
42    inner: Vec<TryParse<T>>,
43}
44
45impl<T: JsonSchema> TryVec<T> {
46    pub fn new(mut vec: Vec<T>) -> Self {
47        let mut vec_marked: Vec<TryParse<T>> = Vec::new();
48        for item in vec.drain(..) {
49            vec_marked.push(TryParse::Parsed(item));
50        }
51        TryVec { inner: vec_marked }
52    }
53
54    pub fn new_empty() -> Self {
55        TryVec { inner: Vec::new() }
56    }
57
58    pub fn take_inner(self) -> Vec<T> {
59        let mut vec: Vec<T> = Vec::new();
60        for item in self.inner {
61            match item {
62                TryParse::Parsed(i) => vec.push(i),
63                _ => continue,
64            };
65        }
66        return vec;
67    }
68}
69
70impl<T: JsonSchema> Serialize for TryVec<T>
71where
72    T: Serialize,
73{
74    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
75    where
76        S: Serializer,
77    {
78        let mut seq = serializer.serialize_seq(Some(self.inner.len()))?;
79        for element in &self.inner {
80            match element {
81                TryParse::Parsed(t) => seq.serialize_element(t)?,
82                _ => continue,
83            };
84        }
85        seq.end()
86    }
87}
88
89struct TryVecVisitor<T: JsonSchema> {
90    marker: PhantomData<fn() -> TryVec<T>>,
91}
92
93impl<T: JsonSchema> TryVecVisitor<T> {
94    fn new() -> Self {
95        TryVecVisitor {
96            marker: PhantomData,
97        }
98    }
99}
100
101impl<'de, T> Visitor<'de> for TryVecVisitor<T>
102where
103    T: DeserializeOwned + JsonSchema,
104{
105    type Value = TryVec<T>;
106
107    // Format a message stating what data this Visitor expects to receive.
108    fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
109        formatter.write_str("a seqence")
110    }
111
112    fn visit_seq<M>(self, mut access: M) -> Result<Self::Value, M::Error>
113    where
114        M: SeqAccess<'de>,
115    {
116        let mut vec = Vec::new();
117
118        loop {
119            let res = match access.next_element() {
120                Ok(val) => val,
121                Err(err) => {
122                    println!(
123                        "Failed to parse event because '{}', the event will be discarded",
124                        err
125                    );
126                    continue;
127                }
128            };
129            match res {
130                Some(item) => vec.push(item),
131                None => break,
132            };
133        }
134
135        Ok(TryVec { inner: vec })
136    }
137}
138
139impl<'de, T: JsonSchema> Deserialize<'de> for TryVec<T>
140where
141    T: DeserializeOwned,
142{
143    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
144    where
145        D: Deserializer<'de>,
146    {
147        deserializer.deserialize_seq(TryVecVisitor::new())
148    }
149}
150
151#[cfg(test)]
152mod test {
153    use schemars::JsonSchema;
154    use serde::{Deserialize, Serialize};
155
156    use super::TryVec;
157
158    #[derive(Deserialize, Serialize, JsonSchema, Debug)]
159    struct TestEvent {
160        data: String,
161    }
162
163    fn assert_serialized_deserialized_eq(data: &str, eq: &str) {
164        let deserialized = serde_json::from_str::<TryVec<TestEvent>>(data).unwrap();
165        let serialized = serde_json::to_string(&deserialized).unwrap();
166        assert_eq!(serialized, eq);
167    }
168
169    #[test]
170    fn test_serialize_deserialize() {
171        println!("test empty array");
172        assert_serialized_deserialized_eq(r#"[]"#, r#"[]"#);
173
174        println!("test one valid event");
175        assert_serialized_deserialized_eq(r#"[{"data":"test"}]"#, r#"[{"data":"test"}]"#);
176
177        println!("test invalid type int, skip event");
178        assert_serialized_deserialized_eq(r#"[{ "data": 1 }]"#, r#"[]"#);
179
180        println!("test invalid type dict, skip event");
181        assert_serialized_deserialized_eq(r#"[{"data":{}}]"#, r#"[]"#);
182
183        println!("test invalid type arr, skip event");
184        assert_serialized_deserialized_eq(r#"[{"data":[]}]"#, r#"[]"#);
185
186        println!("test multiple valid events");
187        assert_serialized_deserialized_eq(
188            r#"[{"data":"test"},{"data":"test2"},{"data":"test3"}]"#,
189            r#"[{"data":"test"},{"data":"test2"},{"data":"test3"}]"#,
190        );
191
192        println!("test invalid event in middle of sequence, skip one event");
193        assert_serialized_deserialized_eq(
194            r#"[{"data":"test"},{"data":2},{"data":"test3"}]"#,
195            r#"[{"data":"test"},{"data":"test3"}]"#,
196        );
197
198        println!("test utf-16 character");
199        assert_serialized_deserialized_eq(r#"[{"data":"\ud835\udc47"}]"#, r#"[{"data":"𝑇"}]"#);
200
201        println!("test invalid utf-8/16, skip event");
202        assert_serialized_deserialized_eq(r#"[{"data":"\ud835"}]"#, r#"[]"#);
203    }
204
205    #[test]
206    fn test_methods() {
207        let tryvec = TryVec::<TestEvent>::new_empty();
208        assert_eq!(tryvec.take_inner().len(), Vec::<TestEvent>::new().len());
209    }
210}