y_octo/doc/codec/
any.rs

1use std::{collections::HashMap, fmt, ops::RangeInclusive};
2
3use ordered_float::OrderedFloat;
4
5use super::*;
6
7const MAX_JS_INT: i64 = 0x001F_FFFF_FFFF_FFFF;
8// The smallest int in js number.
9const MIN_JS_INT: i64 = -MAX_JS_INT;
10pub const JS_INT_RANGE: RangeInclusive<i64> = MIN_JS_INT..=MAX_JS_INT;
11
12#[derive(Debug, Clone, PartialEq)]
13#[cfg_attr(fuzzing, derive(arbitrary::Arbitrary))]
14#[cfg_attr(test, derive(proptest_derive::Arbitrary))]
15pub enum Any {
16    Undefined,
17    Null,
18    Integer(i32),
19    Float32(OrderedFloat<f32>),
20    Float64(OrderedFloat<f64>),
21    BigInt64(i64),
22    False,
23    True,
24    String(String),
25    // FIXME: due to macro's overflow evaluating, we can't use proptest here
26    #[cfg_attr(test, proptest(skip))]
27    Object(HashMap<String, Any>),
28    #[cfg_attr(test, proptest(skip))]
29    Array(Vec<Any>),
30    Binary(Vec<u8>),
31}
32
33impl<R: CrdtReader> CrdtRead<R> for Any {
34    fn read(reader: &mut R) -> JwstCodecResult<Self> {
35        let index = reader.read_u8()?;
36        match 127u8.overflowing_sub(index).0 {
37            0 => Ok(Any::Undefined),
38            1 => Ok(Any::Null),
39            // in yjs implementation, flag 2 only save 32bit integer
40            2 => Ok(Any::Integer(reader.read_var_i32()?)),       // Integer
41            3 => Ok(Any::Float32(reader.read_f32_be()?.into())), // Float32
42            4 => Ok(Any::Float64(reader.read_f64_be()?.into())), // Float64
43            5 => Ok(Any::BigInt64(reader.read_i64_be()?)),       // BigInt64
44            6 => Ok(Any::False),
45            7 => Ok(Any::True),
46            8 => Ok(Any::String(reader.read_var_string()?)), // String
47            9 => {
48                let len = reader.read_var_u64()?;
49                let object = (0..len)
50                    .map(|_| Self::read_key_value(reader))
51                    .collect::<Result<Vec<_>, _>>()?;
52
53                Ok(Any::Object(object.into_iter().collect()))
54            } // Object
55            10 => {
56                let len = reader.read_var_u64()?;
57                let any = (0..len).map(|_| Self::read(reader)).collect::<Result<Vec<_>, _>>()?;
58
59                Ok(Any::Array(any))
60            } // Array
61            11 => {
62                let binary = reader.read_var_buffer()?;
63                Ok(Any::Binary(binary.to_vec()))
64            } // Binary
65            _ => Ok(Any::Undefined),
66        }
67    }
68}
69
70impl<W: CrdtWriter> CrdtWrite<W> for Any {
71    fn write(&self, writer: &mut W) -> JwstCodecResult {
72        match self {
73            Any::Undefined => writer.write_u8(127)?,
74            Any::Null => writer.write_u8(127 - 1)?,
75            Any::Integer(value) => {
76                writer.write_u8(127 - 2)?;
77                writer.write_var_i32(*value)?;
78            }
79            Any::Float32(value) => {
80                writer.write_u8(127 - 3)?;
81                writer.write_f32_be(value.into_inner())?;
82            }
83            Any::Float64(value) => {
84                writer.write_u8(127 - 4)?;
85                writer.write_f64_be(value.into_inner())?;
86            }
87            Any::BigInt64(value) => {
88                writer.write_u8(127 - 5)?;
89                writer.write_i64_be(*value)?;
90            }
91            Any::False => writer.write_u8(127 - 6)?,
92            Any::True => writer.write_u8(127 - 7)?,
93            Any::String(value) => {
94                writer.write_u8(127 - 8)?;
95                writer.write_var_string(value)?;
96            }
97            Any::Object(value) => {
98                writer.write_u8(127 - 9)?;
99                writer.write_var_u64(value.len() as u64)?;
100                for (key, value) in value {
101                    Self::write_key_value(writer, key, value)?;
102                }
103            }
104            Any::Array(values) => {
105                writer.write_u8(127 - 10)?;
106                writer.write_var_u64(values.len() as u64)?;
107                for value in values {
108                    value.write(writer)?;
109                }
110            }
111            Any::Binary(value) => {
112                writer.write_u8(127 - 11)?;
113                writer.write_var_buffer(value)?;
114            }
115        }
116
117        Ok(())
118    }
119}
120
121impl Any {
122    fn read_key_value<R: CrdtReader>(reader: &mut R) -> JwstCodecResult<(String, Any)> {
123        let key = reader.read_var_string()?;
124        let value = Self::read(reader)?;
125
126        Ok((key, value))
127    }
128
129    fn write_key_value<W: CrdtWriter>(writer: &mut W, key: &str, value: &Any) -> JwstCodecResult {
130        writer.write_var_string(key)?;
131        value.write(writer)?;
132
133        Ok(())
134    }
135
136    pub(crate) fn read_multiple<R: CrdtReader>(reader: &mut R) -> JwstCodecResult<Vec<Any>> {
137        let len = reader.read_var_u64()? as usize;
138        let mut vec = Vec::with_capacity(len);
139        for _ in 0..len {
140            vec.push(Any::read(reader)?);
141        }
142
143        Ok(vec)
144    }
145
146    pub(crate) fn write_multiple<W: CrdtWriter>(writer: &mut W, any: &[Any]) -> JwstCodecResult {
147        writer.write_var_u64(any.len() as u64)?;
148        for value in any {
149            value.write(writer)?;
150        }
151
152        Ok(())
153    }
154}
155
156macro_rules! impl_primitive_from {
157    (unsigned, $($ty: ty),*) => {
158        $(
159            impl From<$ty> for Any {
160                fn from(value: $ty) -> Self {
161                    // INFO: i64::MAX > value > u64::MAX will cut down
162                    // yjs binary does not consider the case that the int size exceeds i64
163                    let int: i64 = value as i64;
164                    // handle the behavior same as yjs
165                    if JS_INT_RANGE.contains(&int) {
166                        if int <= i32::MAX as i64 {
167                            Self::Integer(int as i32)
168                        } else if int as f32 as i64 == int {
169                            Self::Float32((int as f32).into())
170                        } else {
171                            Self::Float64((int as f64).into())
172                        }
173                    } else {
174                        Self::BigInt64(int)
175                    }
176                }
177            }
178        )*
179    };
180    (signed, $($ty: ty),*) => {
181        $(
182            impl From<$ty> for Any {
183                fn from(value: $ty) -> Self {
184                    let int: i64 = value.into();
185                    // handle the behavior same as yjs
186                    if JS_INT_RANGE.contains(&int) {
187                        if int <= i32::MAX as i64 {
188                            Self::Integer(int as i32)
189                        } else if int as f32 as i64 == int {
190                            Self::Float32((int as f32).into())
191                        } else {
192                            Self::Float64((int as f64).into())
193                        }
194                    } else {
195                        Self::BigInt64(int)
196                    }
197                }
198            }
199        )*
200    };
201    (string, $($ty: ty),*) => {
202        $(
203            impl From<$ty> for Any {
204                fn from(value: $ty) -> Self {
205                    Self::String(value.into())
206                }
207            }
208        )*
209    };
210}
211
212impl_primitive_from!(unsigned, u8, u16, u32, u64);
213impl_primitive_from!(signed, i8, i16, i32, i64);
214impl_primitive_from!(string, String, &str);
215
216impl From<usize> for Any {
217    fn from(value: usize) -> Self {
218        (value as u64).into()
219    }
220}
221
222impl From<isize> for Any {
223    fn from(value: isize) -> Self {
224        (value as i64).into()
225    }
226}
227
228impl From<f32> for Any {
229    fn from(value: f32) -> Self {
230        Self::Float32(value.into())
231    }
232}
233
234impl From<f64> for Any {
235    fn from(value: f64) -> Self {
236        if value.trunc() == value {
237            (value as i64).into()
238        } else if value as f32 as f64 == value {
239            Self::Float32((value as f32).into())
240        } else {
241            Self::Float64(value.into())
242        }
243    }
244}
245
246impl From<bool> for Any {
247    fn from(value: bool) -> Self {
248        if value {
249            Self::True
250        } else {
251            Self::False
252        }
253    }
254}
255
256impl FromIterator<Any> for Any {
257    fn from_iter<I: IntoIterator<Item = Any>>(iter: I) -> Self {
258        Self::Array(iter.into_iter().collect())
259    }
260}
261
262impl<'a> FromIterator<&'a Any> for Any {
263    fn from_iter<I: IntoIterator<Item = &'a Any>>(iter: I) -> Self {
264        Self::Array(iter.into_iter().cloned().collect())
265    }
266}
267
268impl FromIterator<(String, Any)> for Any {
269    fn from_iter<I: IntoIterator<Item = (String, Any)>>(iter: I) -> Self {
270        let mut map = HashMap::new();
271        map.extend(iter);
272        Self::Object(map)
273    }
274}
275
276impl From<HashMap<String, Any>> for Any {
277    fn from(value: HashMap<String, Any>) -> Self {
278        Self::Object(value)
279    }
280}
281
282impl From<Vec<u8>> for Any {
283    fn from(value: Vec<u8>) -> Self {
284        Self::Binary(value)
285    }
286}
287
288impl From<&[u8]> for Any {
289    fn from(value: &[u8]) -> Self {
290        Self::Binary(value.into())
291    }
292}
293
294// TODO: impl for Any::Undefined
295impl<T: Into<Any>> From<Option<T>> for Any {
296    fn from(value: Option<T>) -> Self {
297        if let Some(val) = value {
298            val.into()
299        } else {
300            Any::Null
301        }
302    }
303}
304
305#[cfg(feature = "serde_json")]
306impl From<serde_json::Value> for Any {
307    fn from(value: serde_json::Value) -> Self {
308        match value {
309            serde_json::Value::Null => Self::Null,
310            serde_json::Value::Bool(b) => {
311                if b {
312                    Self::True
313                } else {
314                    Self::False
315                }
316            }
317            serde_json::Value::Number(n) => {
318                if n.is_f64() {
319                    Self::Float64(n.as_f64().unwrap().into())
320                } else if n.is_i64() {
321                    Self::Integer(n.as_i64().unwrap() as u64)
322                } else {
323                    Self::Integer(n.as_u64().unwrap())
324                }
325            }
326            serde_json::Value::String(s) => Self::String(s),
327            serde_json::Value::Array(vec) => Self::Array(vec.into_iter().map(|v| v.into()).collect::<Vec<_>>()),
328            serde_json::Value::Object(obj) => Self::Object(obj.into_iter().map(|(k, v)| (k, v.into())).collect()),
329        }
330    }
331}
332
333impl<'de> serde::Deserialize<'de> for Any {
334    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
335    where
336        D: serde::Deserializer<'de>,
337    {
338        use serde::de::{Error, MapAccess, SeqAccess, Visitor};
339        struct ValueVisitor;
340
341        impl<'de> Visitor<'de> for ValueVisitor {
342            type Value = Any;
343
344            fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result {
345                formatter.write_str("any valid JSON value")
346            }
347
348            #[inline]
349            fn visit_bool<E>(self, value: bool) -> Result<Any, E> {
350                Ok(if value { Any::True } else { Any::False })
351            }
352
353            #[inline]
354            fn visit_i64<E>(self, value: i64) -> Result<Any, E> {
355                Ok(Any::BigInt64(value))
356            }
357
358            #[inline]
359            fn visit_u64<E>(self, value: u64) -> Result<Any, E> {
360                Ok((value as i64).into())
361            }
362
363            #[inline]
364            fn visit_f64<E>(self, value: f64) -> Result<Any, E> {
365                Ok(Any::Float64(OrderedFloat(value)))
366            }
367
368            #[inline]
369            fn visit_str<E>(self, value: &str) -> Result<Any, E>
370            where
371                E: Error,
372            {
373                self.visit_string(String::from(value))
374            }
375
376            #[inline]
377            fn visit_string<E>(self, value: String) -> Result<Any, E> {
378                Ok(Any::String(value))
379            }
380
381            #[inline]
382            fn visit_none<E>(self) -> Result<Any, E> {
383                Ok(Any::Null)
384            }
385
386            #[inline]
387            fn visit_some<D>(self, deserializer: D) -> Result<Any, D::Error>
388            where
389                D: serde::Deserializer<'de>,
390            {
391                serde::Deserialize::deserialize(deserializer)
392            }
393
394            #[inline]
395            fn visit_unit<E>(self) -> Result<Any, E> {
396                Ok(Any::Null)
397            }
398
399            #[inline]
400            fn visit_seq<V>(self, mut visitor: V) -> Result<Any, V::Error>
401            where
402                V: SeqAccess<'de>,
403            {
404                let mut vec = Vec::new();
405
406                while let Some(elem) = visitor.next_element()? {
407                    vec.push(elem);
408                }
409
410                Ok(Any::Array(vec))
411            }
412
413            fn visit_map<V>(self, mut visitor: V) -> Result<Any, V::Error>
414            where
415                V: MapAccess<'de>,
416            {
417                match visitor.next_key::<String>()? {
418                    Some(k) => {
419                        let mut values = HashMap::new();
420
421                        values.insert(k, visitor.next_value()?);
422                        while let Some((key, value)) = visitor.next_entry()? {
423                            values.insert(key, value);
424                        }
425
426                        Ok(Any::Object(values))
427                    }
428                    None => Ok(Any::Object(HashMap::new())),
429                }
430            }
431        }
432
433        deserializer.deserialize_any(ValueVisitor)
434    }
435}
436
437impl serde::Serialize for Any {
438    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
439    where
440        S: serde::Serializer,
441    {
442        use serde::ser::{SerializeMap, SerializeSeq};
443
444        match self {
445            Any::Null => serializer.serialize_none(),
446            Any::Undefined => serializer.serialize_none(),
447            Any::True => serializer.serialize_bool(true),
448            Any::False => serializer.serialize_bool(false),
449            Any::Float32(value) => serializer.serialize_f32(value.0),
450            Any::Float64(value) => serializer.serialize_f64(value.0),
451            Any::Integer(value) => serializer.serialize_i32(*value),
452            Any::BigInt64(value) => serializer.serialize_i64(*value),
453            Any::String(value) => serializer.serialize_str(value.as_ref()),
454            Any::Array(values) => {
455                let mut seq = serializer.serialize_seq(Some(values.len()))?;
456                for value in values.iter() {
457                    seq.serialize_element(value)?;
458                }
459                seq.end()
460            }
461            Any::Object(entries) => {
462                let mut map = serializer.serialize_map(Some(entries.len()))?;
463                for (key, value) in entries.iter() {
464                    map.serialize_entry(key, value)?;
465                }
466                map.end()
467            }
468            Any::Binary(buf) => serializer.serialize_bytes(buf),
469        }
470    }
471}
472
473impl ToString for Any {
474    fn to_string(&self) -> String {
475        match self {
476            Self::True => "true".to_string(),
477            Self::False => "false".to_string(),
478            Self::String(s) => s.clone(),
479            Self::Integer(i) => i.to_string(),
480            Self::Float32(f) => f.to_string(),
481            Self::Float64(f) => f.to_string(),
482            Self::BigInt64(i) => i.to_string(),
483            // TODO: stringify other types
484            _ => {
485                debug!("any to string {:?}", self);
486                String::default()
487            }
488        }
489    }
490}
491
492#[cfg(test)]
493mod tests {
494    use proptest::{collection::vec, prelude::*};
495
496    use super::*;
497
498    #[test]
499    fn test_any_codec() {
500        let any = Any::Object(
501            vec![
502                ("name".to_string(), Any::String("Alice".to_string())),
503                ("age".to_string(), Any::Integer(25)),
504                (
505                    "contacts".to_string(),
506                    Any::Array(vec![
507                        Any::Object(
508                            vec![
509                                ("type".to_string(), Any::String("Mobile".to_string())),
510                                ("number".to_string(), Any::String("1234567890".to_string())),
511                            ]
512                            .into_iter()
513                            .collect(),
514                        ),
515                        Any::Object(
516                            vec![
517                                ("type".to_string(), Any::String("Email".to_string())),
518                                ("address".to_string(), Any::String("alice@example.com".to_string())),
519                            ]
520                            .into_iter()
521                            .collect(),
522                        ),
523                        Any::Undefined,
524                    ]),
525                ),
526                (
527                    "standard_data".to_string(),
528                    Any::Array(vec![
529                        Any::Undefined,
530                        Any::Null,
531                        Any::Integer(114514),
532                        Any::Float32(114.514.into()),
533                        Any::Float64(115.514.into()),
534                        Any::BigInt64(-1145141919810),
535                        Any::False,
536                        Any::True,
537                        Any::Object(
538                            vec![
539                                ("name".to_string(), Any::String("tadokoro".to_string())),
540                                ("age".to_string(), Any::String("24".to_string())),
541                                ("profession".to_string(), Any::String("student".to_string())),
542                            ]
543                            .into_iter()
544                            .collect(),
545                        ),
546                        Any::Binary(vec![1, 2, 3, 4, 5]),
547                    ]),
548                ),
549            ]
550            .into_iter()
551            .collect(),
552        );
553
554        let mut encoder = RawEncoder::default();
555        any.write(&mut encoder).unwrap();
556        let encoded = encoder.into_inner();
557
558        let mut decoder = RawDecoder::new(encoded);
559        let decoded = Any::read(&mut decoder).unwrap();
560
561        assert_eq!(any, decoded);
562    }
563
564    proptest! {
565        #[test]
566        #[cfg_attr(miri, ignore)]
567        fn test_random_any(any in vec(any::<Any>(), 0..100)) {
568            for any in &any {
569                let mut encoder = RawEncoder::default();
570                any.write(&mut encoder).unwrap();
571                let encoded = encoder.into_inner();
572
573                let mut decoder = RawDecoder::new(encoded);
574                let decoded = Any::read(&mut decoder).unwrap();
575
576                assert_eq!(any, &decoded);
577            }
578        }
579    }
580
581    #[test]
582    fn test_convert_to_any() {
583        let any: Vec<Any> = vec![
584            42u8.into(),
585            42u16.into(),
586            42u32.into(),
587            42u64.into(),
588            114.514f32.into(),
589            1919.810f64.into(),
590            (-42i8).into(),
591            (-42i16).into(),
592            (-42i32).into(),
593            (-42i64).into(),
594            false.into(),
595            true.into(),
596            "JWST".to_string().into(),
597            "OctoBase".into(),
598            vec![1u8, 9, 1, 9].into(),
599            (&[8u8, 1, 0][..]).into(),
600            [Any::True, 42u8.into()].iter().collect(),
601        ];
602        assert_eq!(
603            any,
604            vec![
605                Any::Integer(42),
606                Any::Integer(42),
607                Any::Integer(42),
608                Any::Integer(42),
609                Any::Float32(114.514.into()),
610                Any::Float64(1919.810.into()),
611                Any::Integer(-42),
612                Any::Integer(-42),
613                Any::Integer(-42),
614                Any::Integer(-42),
615                Any::False,
616                Any::True,
617                Any::String("JWST".to_string()),
618                Any::String("OctoBase".to_string()),
619                Any::Binary(vec![1, 9, 1, 9]),
620                Any::Binary(vec![8, 1, 0]),
621                Any::Array(vec![Any::True, Any::Integer(42)])
622            ]
623        );
624
625        assert_eq!(
626            vec![("key".to_string(), 10u64.into())].into_iter().collect::<Any>(),
627            Any::Object(HashMap::from_iter(vec![("key".to_string(), Any::Integer(10))]))
628        );
629
630        let any: Any = 10u64.into();
631        assert_eq!([any].iter().collect::<Any>(), Any::Array(vec![Any::Integer(10)]));
632    }
633}