Skip to main content

feldera_ijson/
rkyv.rs

1use std::{collections::BTreeMap, convert::TryFrom, iter::FromIterator};
2
3use ordered_float::OrderedFloat;
4use rkyv::{
5    ser::{ScratchSpace, Serializer},
6    Serialize,
7};
8use rkyv::{Archive, Archived, Deserialize, Fallible};
9
10use crate::{IArray, INumber, IObject, IString};
11
12use super::value::IValue;
13
14#[derive(
15    Debug, rkyv::Serialize, rkyv::Deserialize, rkyv::Archive, PartialOrd, PartialEq, Eq, Ord,
16)]
17#[archive(bound(serialize = "__S: rkyv::ser::ScratchSpace + rkyv::ser::Serializer"))]
18#[archive(check_bytes)]
19#[archive_attr(check_bytes(
20    bound = "__C: rkyv::validation::ArchiveContext, <__C as rkyv::Fallible>::Error: rkyv::bytecheck::Error"
21))]
22#[archive_attr(derive(PartialEq, Eq, PartialOrd, Ord))]
23pub enum ArchivableJson {
24    Null,
25    Bool(bool),
26    Number(JsonNumber),
27    String(String),
28    Array(
29        #[omit_bounds]
30        #[archive_attr(omit_bounds)]
31        Vec<ArchivableJson>,
32    ),
33    Object(
34        #[omit_bounds]
35        #[archive_attr(omit_bounds)]
36        BTreeMap<String, ArchivableJson>,
37    ),
38}
39
40#[derive(Archive, Debug, Deserialize, Serialize, PartialEq, PartialOrd, Eq, Ord)]
41#[archive(check_bytes)]
42#[archive_attr(derive(PartialEq, Eq, PartialOrd, Ord))]
43pub enum JsonNumber {
44    PosInt(u64),
45    NegInt(i64),
46    Float(OrderedFloat<f64>),
47}
48
49impl From<&IValue> for ArchivableJson {
50    fn from(value: &IValue) -> Self {
51        match value.destructure_ref() {
52            crate::DestructuredRef::Null => ArchivableJson::Null,
53            crate::DestructuredRef::Bool(b) => ArchivableJson::Bool(b),
54            crate::DestructuredRef::Number(n) => ArchivableJson::Number({
55                if n.has_decimal_point() {
56                    JsonNumber::Float(n.to_f64().unwrap().into())
57                } else if let Some(v) = n.to_i64() {
58                    JsonNumber::NegInt(v)
59                } else {
60                    JsonNumber::PosInt(n.to_u64().unwrap())
61                }
62            }),
63            crate::DestructuredRef::String(s) => ArchivableJson::String(s.to_string()),
64            crate::DestructuredRef::Array(a) => {
65                ArchivableJson::Array(a.into_iter().map(ArchivableJson::from).collect())
66            }
67            crate::DestructuredRef::Object(obj) => ArchivableJson::Object(
68                obj.into_iter()
69                    .map(|(k, v)| (k.to_string(), ArchivableJson::from(v)))
70                    .collect(),
71            ),
72        }
73    }
74}
75
76impl From<IValue> for ArchivableJson {
77    fn from(value: IValue) -> Self {
78        ArchivableJson::from(&value)
79    }
80}
81
82impl From<ArchivableJson> for IValue {
83    fn from(value: ArchivableJson) -> Self {
84        match value {
85            ArchivableJson::Null => IValue::NULL,
86            ArchivableJson::Bool(b) => {
87                if b {
88                    IValue::TRUE
89                } else {
90                    IValue::FALSE
91                }
92            }
93            ArchivableJson::Number(n) => match n {
94                JsonNumber::PosInt(u) => INumber::from(u).into(),
95                JsonNumber::NegInt(neg) => INumber::from(neg).into(),
96                JsonNumber::Float(f) => INumber::try_from(f.into_inner())
97                    .expect("unexpected float")
98                    .into(),
99            },
100            ArchivableJson::String(s) => IString::from(s).into(),
101            ArchivableJson::Array(arr) => {
102                let new: Vec<IValue> = arr.into_iter().map(IValue::from).collect();
103                IArray::from(new).into()
104            }
105            ArchivableJson::Object(obj) => IObject::from_iter(obj).into(),
106        }
107    }
108}
109
110impl<S: Serializer + ScratchSpace> Serialize<S> for IValue {
111    fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
112        ArchivableJson::from(self).serialize(serializer)
113    }
114}
115
116impl Archive for IValue {
117    type Archived = <ArchivableJson as Archive>::Archived;
118    type Resolver = <ArchivableJson as Archive>::Resolver;
119
120    unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
121        ArchivableJson::from(self).resolve(pos, resolver, out)
122    }
123}
124
125impl<D: Fallible + ?Sized> Deserialize<IValue, D> for Archived<IValue> {
126    fn deserialize(&self, deserializer: &mut D) -> Result<IValue, D::Error> {
127        let r: ArchivableJson = rkyv::Deserialize::deserialize(self, deserializer)?;
128
129        Ok(IValue::from(r))
130    }
131}
132
133impl<S: Serializer + ScratchSpace> Serialize<S> for IString {
134    fn serialize(&self, serializer: &mut S) -> Result<Self::Resolver, S::Error> {
135        self.to_string().serialize(serializer)
136    }
137}
138
139impl Archive for IString {
140    type Archived = <String as Archive>::Archived;
141    type Resolver = <String as Archive>::Resolver;
142
143    unsafe fn resolve(&self, pos: usize, resolver: Self::Resolver, out: *mut Self::Archived) {
144        self.to_string().resolve(pos, resolver, out)
145    }
146}
147
148impl<D: Fallible + ?Sized> Deserialize<IString, D> for Archived<IString> {
149    fn deserialize(&self, deserializer: &mut D) -> Result<IString, D::Error> {
150        let r: String = rkyv::Deserialize::deserialize(self, deserializer)?;
151
152        Ok(IString::from(r))
153    }
154}
155
156#[cfg(test)]
157mod tests {
158    use rkyv::Deserialize;
159
160    use crate::{IString, IValue};
161
162    use super::ArchivableJson;
163
164    #[test]
165    fn test_serialization() {
166        let x: IValue = serde_json::from_str(
167            r#"
168        {
169            "songs": [
170                {
171                  "title": "Fairies Wear Boots",
172                  "artist": "Black Sabbath",
173                  "album": "Paranoid",
174                  "release_year": 1970,
175                  "genre": ["Heavy Metal", "Hard Rock"]
176                },
177                {
178                  "title": "Whole Lotta Love",
179                  "artist": "Led Zeppelin",
180                  "album": "Led Zeppelin II",
181                  "release_year": 1969,
182                  "genre": ["Hard Rock", "Blues Rock"]
183                },
184                {
185                  "title": "Hysteria",
186                  "artist": "Muse",
187                  "album": "Absolution",
188                  "release_year": 2003,
189                  "genre": ["Alternative Rock", "Art Rock"]
190                },
191                {
192                  "title": "Bohemian Rhapsody",
193                  "artist": "Queen",
194                  "album": "A Night at the Opera",
195                  "release_year": 1975,
196                  "genre": ["Progressive Rock", "Symphonic Rock"]
197                },
198                {
199                  "title": "Hotel California",
200                  "artist": "Eagles",
201                  "album": "Hotel California",
202                  "release_year": 1976,
203                  "genre": ["Rock", "Soft Rock"]
204                },
205                {
206                  "title": "Smells Like Teen Spirit",
207                  "artist": "Nirvana",
208                  "album": "Nevermind",
209                  "release_year": 1991,
210                  "genre": ["Grunge", "Alternative Rock"]
211                },
212                {
213                  "title": "Stairway to Heaven",
214                  "artist": "Led Zeppelin",
215                  "album": "Led Zeppelin IV",
216                  "release_year": 1971,
217                  "genre": ["Hard Rock", "Folk Rock"]
218                },
219                {
220                  "title": "Imagine",
221                  "artist": "John Lennon",
222                  "album": "Imagine",
223                  "release_year": 1971,
224                  "genre": ["Soft Rock", "Pop"]
225                },
226                {
227                  "title": "Yesterday",
228                  "artist": "The Beatles",
229                  "album": "Help!",
230                  "release_year": 1965,
231                  "genre": ["Folk Rock", "Baroque Pop"]
232                }
233            ]
234        }
235        "#,
236        )
237        .unwrap();
238
239        let encoded = rkyv::to_bytes::<_, 256>(&x).unwrap();
240        let archived = unsafe { rkyv::archived_root::<ArchivableJson>(&encoded[..]) };
241        let decoded: IValue = archived.deserialize(&mut rkyv::Infallible).unwrap();
242
243        assert_eq!(x, decoded);
244    }
245
246    #[test]
247    fn test_string_serialization() {
248        let s = "hello".to_string();
249
250        let encoded = rkyv::to_bytes::<_, 256>(&s).unwrap();
251        let archived = unsafe { rkyv::archived_root::<String>(&encoded[..]) };
252        let decoded: IString = archived.deserialize(&mut rkyv::Infallible).unwrap();
253
254        assert_eq!(s, decoded);
255    }
256}