y_octo/doc/codec/
any.rs

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