Skip to main content

loro_common/
value.rs

1use std::{collections::HashMap, hash::Hash, ops::Index, sync::Arc};
2
3use arbitrary::Arbitrary;
4use enum_as_inner::EnumAsInner;
5use rustc_hash::FxHashMap;
6use serde::{de::VariantAccess, Deserialize, Serialize};
7
8use crate::ContainerID;
9
10/// [LoroValue] is used to represents the state of CRDT at a given version.
11///
12/// This struct is cheap to clone, the time complexity is O(1).
13#[derive(Debug, Clone, EnumAsInner, Default)]
14pub enum LoroValue {
15    #[default]
16    Null,
17    Bool(bool),
18    Double(f64),
19    I64(i64),
20    // i64?
21    Binary(LoroBinaryValue),
22    String(LoroStringValue),
23    List(LoroListValue),
24    // PERF We can use InternalString as key
25    Map(LoroMapValue),
26    Container(ContainerID),
27}
28
29impl PartialEq for LoroValue {
30    fn eq(&self, other: &Self) -> bool {
31        match (self, other) {
32            (LoroValue::Null, LoroValue::Null) => true,
33            (LoroValue::Bool(a), LoroValue::Bool(b)) => a == b,
34            (LoroValue::Double(a), LoroValue::Double(b)) => a == b || (a.is_nan() && b.is_nan()),
35            (LoroValue::I64(a), LoroValue::I64(b)) => a == b,
36            (LoroValue::Binary(a), LoroValue::Binary(b)) => a == b,
37            (LoroValue::String(a), LoroValue::String(b)) => a == b,
38            (LoroValue::List(a), LoroValue::List(b)) => a == b,
39            (LoroValue::Map(a), LoroValue::Map(b)) => a == b,
40            (LoroValue::Container(a), LoroValue::Container(b)) => a == b,
41            _ => false,
42        }
43    }
44}
45
46#[derive(Default, Debug, PartialEq, Clone, Arbitrary)]
47pub struct LoroBinaryValue(Arc<Vec<u8>>);
48#[derive(Default, Debug, PartialEq, Clone, Arbitrary)]
49pub struct LoroStringValue(Arc<String>);
50#[derive(Default, Debug, PartialEq, Clone, Arbitrary)]
51pub struct LoroListValue(Arc<Vec<LoroValue>>);
52#[derive(Default, Debug, PartialEq, Clone, Arbitrary)]
53pub struct LoroMapValue(Arc<FxHashMap<String, LoroValue>>);
54
55impl From<Vec<u8>> for LoroBinaryValue {
56    fn from(value: Vec<u8>) -> Self {
57        LoroBinaryValue(Arc::new(value))
58    }
59}
60
61impl From<String> for LoroStringValue {
62    fn from(value: String) -> Self {
63        LoroStringValue(Arc::new(value))
64    }
65}
66
67impl From<&str> for LoroStringValue {
68    fn from(value: &str) -> Self {
69        LoroStringValue(Arc::new(value.to_string()))
70    }
71}
72
73impl From<Vec<LoroValue>> for LoroListValue {
74    fn from(value: Vec<LoroValue>) -> Self {
75        LoroListValue(Arc::new(value))
76    }
77}
78
79impl From<FxHashMap<String, LoroValue>> for LoroMapValue {
80    fn from(value: FxHashMap<String, LoroValue>) -> Self {
81        LoroMapValue(Arc::new(value))
82    }
83}
84
85impl From<HashMap<String, LoroValue>> for LoroMapValue {
86    fn from(value: HashMap<String, LoroValue>) -> Self {
87        LoroMapValue(Arc::new(FxHashMap::from_iter(value)))
88    }
89}
90
91impl From<Vec<(String, LoroValue)>> for LoroMapValue {
92    fn from(value: Vec<(String, LoroValue)>) -> Self {
93        LoroMapValue(Arc::new(FxHashMap::from_iter(value)))
94    }
95}
96
97impl std::ops::Deref for LoroBinaryValue {
98    type Target = Vec<u8>;
99    fn deref(&self) -> &Self::Target {
100        &self.0
101    }
102}
103
104impl std::ops::Deref for LoroStringValue {
105    type Target = String;
106    fn deref(&self) -> &Self::Target {
107        &self.0
108    }
109}
110
111impl std::ops::Deref for LoroListValue {
112    type Target = Vec<LoroValue>;
113    fn deref(&self) -> &Self::Target {
114        &self.0
115    }
116}
117
118impl std::ops::Deref for LoroMapValue {
119    type Target = FxHashMap<String, LoroValue>;
120    fn deref(&self) -> &Self::Target {
121        &self.0
122    }
123}
124
125impl LoroBinaryValue {
126    pub fn make_mut(&mut self) -> &mut Vec<u8> {
127        Arc::make_mut(&mut self.0)
128    }
129}
130
131impl LoroStringValue {
132    pub fn make_mut(&mut self) -> &mut String {
133        Arc::make_mut(&mut self.0)
134    }
135}
136
137impl LoroListValue {
138    pub fn make_mut(&mut self) -> &mut Vec<LoroValue> {
139        Arc::make_mut(&mut self.0)
140    }
141}
142
143impl LoroMapValue {
144    pub fn make_mut(&mut self) -> &mut FxHashMap<String, LoroValue> {
145        Arc::make_mut(&mut self.0)
146    }
147}
148
149impl LoroBinaryValue {
150    pub fn unwrap(self) -> Vec<u8> {
151        match Arc::try_unwrap(self.0) {
152            Ok(v) => v,
153            Err(arc) => (*arc).clone(),
154        }
155    }
156}
157
158impl LoroStringValue {
159    pub fn unwrap(self) -> String {
160        match Arc::try_unwrap(self.0) {
161            Ok(v) => v,
162            Err(arc) => (*arc).clone(),
163        }
164    }
165}
166
167impl LoroListValue {
168    pub fn unwrap(self) -> Vec<LoroValue> {
169        match Arc::try_unwrap(self.0) {
170            Ok(v) => v,
171            Err(arc) => (*arc).clone(),
172        }
173    }
174}
175
176impl LoroMapValue {
177    pub fn unwrap(self) -> FxHashMap<String, LoroValue> {
178        match Arc::try_unwrap(self.0) {
179            Ok(v) => v,
180            Err(arc) => (*arc).clone(),
181        }
182    }
183}
184
185impl FromIterator<LoroValue> for LoroListValue {
186    fn from_iter<T: IntoIterator<Item = LoroValue>>(iter: T) -> Self {
187        LoroListValue(Arc::new(iter.into_iter().collect()))
188    }
189}
190
191impl FromIterator<(String, LoroValue)> for LoroMapValue {
192    fn from_iter<T: IntoIterator<Item = (String, LoroValue)>>(iter: T) -> Self {
193        let map: FxHashMap<_, _> = iter.into_iter().collect();
194        LoroMapValue(Arc::new(map))
195    }
196}
197
198impl AsRef<str> for LoroStringValue {
199    fn as_ref(&self) -> &str {
200        &self.0
201    }
202}
203
204impl AsRef<[LoroValue]> for LoroListValue {
205    fn as_ref(&self) -> &[LoroValue] {
206        &self.0
207    }
208}
209
210impl AsRef<FxHashMap<String, LoroValue>> for LoroMapValue {
211    fn as_ref(&self) -> &FxHashMap<String, LoroValue> {
212        &self.0
213    }
214}
215
216const MAX_DEPTH: usize = 128;
217impl<'a> arbitrary::Arbitrary<'a> for LoroValue {
218    fn arbitrary(u: &mut arbitrary::Unstructured<'a>) -> arbitrary::Result<Self> {
219        let value = match u.int_in_range(0..=7).unwrap() {
220            0 => LoroValue::Null,
221            1 => LoroValue::Bool(u.arbitrary()?),
222            2 => LoroValue::Double(u.arbitrary()?),
223            3 => LoroValue::I64(u.arbitrary()?),
224            4 => LoroValue::Binary(LoroBinaryValue::arbitrary(u)?),
225            5 => LoroValue::String(LoroStringValue::arbitrary(u)?),
226            6 => LoroValue::List(LoroListValue::arbitrary(u)?),
227            7 => LoroValue::Map(LoroMapValue::arbitrary(u)?),
228            _ => unreachable!(),
229        };
230
231        if value.get_depth() > MAX_DEPTH {
232            Err(arbitrary::Error::IncorrectFormat)
233        } else {
234            Ok(value)
235        }
236    }
237}
238
239impl LoroValue {
240    pub fn get_by_key(&self, key: &str) -> Option<&LoroValue> {
241        match self {
242            LoroValue::Map(map) => map.get(key),
243            _ => None,
244        }
245    }
246
247    pub fn get_by_index(&self, index: isize) -> Option<&LoroValue> {
248        match self {
249            LoroValue::List(list) => {
250                if index < 0 {
251                    let offset = usize::try_from(index.checked_neg()?).ok()?;
252                    list.get(list.len().checked_sub(offset)?)
253                } else {
254                    list.get(usize::try_from(index).ok()?)
255                }
256            }
257            _ => None,
258        }
259    }
260
261    pub fn is_false(&self) -> bool {
262        match self {
263            LoroValue::Bool(b) => !*b,
264            _ => false,
265        }
266    }
267
268    pub fn get_depth(&self) -> usize {
269        let mut max_depth = 0;
270        let mut value_depth_pairs = vec![(self, 0)];
271        while let Some((value, depth)) = value_depth_pairs.pop() {
272            match value {
273                LoroValue::List(arr) => {
274                    for v in arr.iter() {
275                        value_depth_pairs.push((v, depth + 1));
276                    }
277                    max_depth = max_depth.max(depth + 1);
278                }
279                LoroValue::Map(map) => {
280                    for (_, v) in map.iter() {
281                        value_depth_pairs.push((v, depth + 1));
282                    }
283
284                    max_depth = max_depth.max(depth + 1);
285                }
286                _ => {}
287            }
288        }
289
290        max_depth
291    }
292
293    // TODO: add checks for too deep value, and return err if users
294    // try to insert such value into a container
295    pub fn is_too_deep(&self) -> bool {
296        self.get_depth() > MAX_DEPTH
297    }
298
299    /// Visit the all list items or map's values
300    pub fn visit_children(&self, f: &mut dyn FnMut(&LoroValue)) {
301        match self {
302            LoroValue::List(list) => {
303                for v in list.iter() {
304                    f(v);
305                }
306            }
307            LoroValue::Map(m) => {
308                for (_k, v) in m.iter() {
309                    f(v)
310                }
311            }
312            _ => {}
313        }
314    }
315
316    pub fn is_empty_collection(&self) -> bool {
317        match self {
318            LoroValue::Null => false,
319            LoroValue::Bool(_) => false,
320            LoroValue::Double(_) => false,
321            LoroValue::I64(_) => false,
322            LoroValue::Binary(loro_binary_value) => loro_binary_value.is_empty(),
323            LoroValue::String(loro_string_value) => loro_string_value.is_empty(),
324            LoroValue::List(loro_list_value) => loro_list_value.is_empty(),
325            LoroValue::Map(loro_map_value) => loro_map_value.is_empty(),
326            LoroValue::Container(_) => false,
327        }
328    }
329}
330
331impl Index<&str> for LoroValue {
332    type Output = LoroValue;
333
334    fn index(&self, index: &str) -> &Self::Output {
335        match self {
336            LoroValue::Map(map) => map.get(index).unwrap_or(&LoroValue::Null),
337            _ => &LoroValue::Null,
338        }
339    }
340}
341
342impl Index<usize> for LoroValue {
343    type Output = LoroValue;
344
345    fn index(&self, index: usize) -> &Self::Output {
346        match self {
347            LoroValue::List(list) => list.get(index).unwrap_or(&LoroValue::Null),
348            _ => &LoroValue::Null,
349        }
350    }
351}
352
353impl TryFrom<LoroValue> for bool {
354    type Error = &'static str;
355
356    fn try_from(value: LoroValue) -> Result<Self, Self::Error> {
357        match value {
358            LoroValue::Bool(v) => Ok(v),
359            _ => Err("not a bool"),
360        }
361    }
362}
363
364impl TryFrom<LoroValue> for f64 {
365    type Error = &'static str;
366
367    fn try_from(value: LoroValue) -> Result<Self, Self::Error> {
368        match value {
369            LoroValue::Double(v) => Ok(v),
370            _ => Err("not a double"),
371        }
372    }
373}
374
375impl TryFrom<LoroValue> for i32 {
376    type Error = &'static str;
377
378    fn try_from(value: LoroValue) -> Result<Self, Self::Error> {
379        match value {
380            LoroValue::I64(v) => i32::try_from(v).map_err(|_| "i64 out of i32 range"),
381            _ => Err("not a i32"),
382        }
383    }
384}
385
386impl TryFrom<LoroValue> for Arc<Vec<u8>> {
387    type Error = &'static str;
388
389    fn try_from(value: LoroValue) -> Result<Self, Self::Error> {
390        match value {
391            LoroValue::Binary(v) => Ok(Arc::clone(&v.0)),
392            _ => Err("not a binary"),
393        }
394    }
395}
396
397impl TryFrom<LoroValue> for Arc<String> {
398    type Error = &'static str;
399
400    fn try_from(value: LoroValue) -> Result<Self, Self::Error> {
401        match value {
402            LoroValue::String(v) => Ok(Arc::clone(&v.0)),
403            _ => Err("not a string"),
404        }
405    }
406}
407
408impl TryFrom<LoroValue> for Arc<Vec<LoroValue>> {
409    type Error = &'static str;
410
411    fn try_from(value: LoroValue) -> Result<Self, Self::Error> {
412        match value {
413            LoroValue::List(v) => Ok(Arc::clone(&v.0)),
414            _ => Err("not a list"),
415        }
416    }
417}
418
419impl TryFrom<LoroValue> for Arc<FxHashMap<String, LoroValue>> {
420    type Error = &'static str;
421
422    fn try_from(value: LoroValue) -> Result<Self, Self::Error> {
423        match value {
424            LoroValue::Map(v) => Ok(Arc::clone(&v.0)),
425            _ => Err("not a map"),
426        }
427    }
428}
429
430impl TryFrom<LoroValue> for ContainerID {
431    type Error = &'static str;
432
433    fn try_from(value: LoroValue) -> Result<Self, Self::Error> {
434        match value {
435            LoroValue::Container(v) => Ok(v),
436            _ => Err("not a container"),
437        }
438    }
439}
440
441impl Hash for LoroValue {
442    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
443        std::mem::discriminant(self).hash(state);
444        match self {
445            LoroValue::Null => {}
446            LoroValue::Bool(v) => {
447                state.write_u8(*v as u8);
448            }
449            LoroValue::Double(v) => {
450                let normalized = if v.is_nan() {
451                    f64::NAN
452                } else if *v == 0.0 {
453                    0.0
454                } else {
455                    *v
456                };
457                state.write_u64(normalized.to_bits());
458            }
459            LoroValue::I64(v) => {
460                state.write_i64(*v);
461            }
462            LoroValue::Binary(v) => {
463                v.hash(state);
464            }
465            LoroValue::String(v) => {
466                v.hash(state);
467            }
468            LoroValue::List(v) => {
469                v.hash(state);
470            }
471            LoroValue::Map(v) => {
472                state.write_usize(v.len());
473                let mut entries: Vec<_> = v.iter().collect();
474                entries.sort_unstable_by_key(|(k, _)| *k);
475                for (k, v) in entries {
476                    k.hash(state);
477                    v.hash(state);
478                }
479            }
480            LoroValue::Container(v) => {
481                v.hash(state);
482            }
483        }
484    }
485}
486
487impl Eq for LoroValue {}
488
489impl<S: Into<String>, M> From<HashMap<S, LoroValue, M>> for LoroValue {
490    fn from(map: HashMap<S, LoroValue, M>) -> Self {
491        let mut new_map = FxHashMap::default();
492        for (k, v) in map {
493            new_map.insert(k.into(), v);
494        }
495
496        LoroValue::Map(new_map.into())
497    }
498}
499
500impl From<Vec<u8>> for LoroValue {
501    fn from(vec: Vec<u8>) -> Self {
502        LoroValue::Binary(vec.into())
503    }
504}
505
506impl From<&'_ [u8]> for LoroValue {
507    fn from(vec: &[u8]) -> Self {
508        LoroValue::Binary(vec.to_vec().into())
509    }
510}
511
512impl<const N: usize> From<&'_ [u8; N]> for LoroValue {
513    fn from(vec: &[u8; N]) -> Self {
514        LoroValue::Binary(vec.to_vec().into())
515    }
516}
517
518impl From<i32> for LoroValue {
519    fn from(v: i32) -> Self {
520        LoroValue::I64(v as i64)
521    }
522}
523
524impl From<u32> for LoroValue {
525    fn from(v: u32) -> Self {
526        LoroValue::I64(v as i64)
527    }
528}
529
530impl From<i64> for LoroValue {
531    fn from(v: i64) -> Self {
532        LoroValue::I64(v)
533    }
534}
535
536impl From<u16> for LoroValue {
537    fn from(v: u16) -> Self {
538        LoroValue::I64(v as i64)
539    }
540}
541
542impl From<i16> for LoroValue {
543    fn from(v: i16) -> Self {
544        LoroValue::I64(v as i64)
545    }
546}
547
548impl From<f64> for LoroValue {
549    fn from(v: f64) -> Self {
550        LoroValue::Double(v)
551    }
552}
553
554impl From<bool> for LoroValue {
555    fn from(v: bool) -> Self {
556        LoroValue::Bool(v)
557    }
558}
559
560impl<T: Into<LoroValue>> From<Vec<T>> for LoroValue {
561    fn from(value: Vec<T>) -> Self {
562        let vec: Vec<LoroValue> = value.into_iter().map(|x| x.into()).collect();
563        LoroValue::List(vec.into())
564    }
565}
566
567impl From<&str> for LoroValue {
568    fn from(v: &str) -> Self {
569        LoroValue::String(v.to_string().into())
570    }
571}
572
573impl From<String> for LoroValue {
574    fn from(v: String) -> Self {
575        LoroValue::String(v.into())
576    }
577}
578
579impl<'a> From<&'a [LoroValue]> for LoroValue {
580    fn from(v: &'a [LoroValue]) -> Self {
581        LoroValue::List(v.to_vec().into())
582    }
583}
584
585impl From<ContainerID> for LoroValue {
586    fn from(v: ContainerID) -> Self {
587        LoroValue::Container(v)
588    }
589}
590
591#[cfg(feature = "wasm")]
592pub mod wasm {
593    use js_sys::{Array, Object, Uint8Array};
594    use rustc_hash::FxHashMap;
595    use wasm_bindgen::{__rt::IntoJsResult, JsCast, JsValue};
596
597    use crate::{ContainerID, LoroError, LoroValue};
598
599    pub fn convert(value: LoroValue) -> JsValue {
600        match value {
601            LoroValue::Null => JsValue::NULL,
602            LoroValue::Bool(b) => JsValue::from_bool(b),
603            LoroValue::Double(f) => JsValue::from_f64(f),
604            LoroValue::I64(i) => JsValue::from_f64(i as f64),
605            LoroValue::String(s) => JsValue::from_str(&s),
606            LoroValue::Binary(binary) => {
607                let binary = binary.unwrap();
608                let arr = Uint8Array::new_with_length(binary.len() as u32);
609                for (i, v) in binary.into_iter().enumerate() {
610                    arr.set_index(i as u32, v);
611                }
612                arr.into_js_result().unwrap()
613            }
614            LoroValue::List(list) => {
615                let list = list.unwrap();
616                let arr = Array::new_with_length(list.len() as u32);
617                for (i, v) in list.into_iter().enumerate() {
618                    arr.set(i as u32, convert(v));
619                }
620                arr.into_js_result().unwrap()
621            }
622            LoroValue::Map(m) => {
623                let m = m.unwrap();
624                let map = Object::new();
625                for (k, v) in m.into_iter() {
626                    let str: &str = &k;
627                    js_sys::Reflect::set(&map, &JsValue::from_str(str), &convert(v)).unwrap();
628                }
629
630                map.into_js_result().unwrap()
631            }
632            LoroValue::Container(container_id) => JsValue::from(&container_id),
633        }
634    }
635
636    impl From<LoroValue> for JsValue {
637        fn from(value: LoroValue) -> Self {
638            convert(value)
639        }
640    }
641
642    impl From<JsValue> for LoroValue {
643        fn from(js_value: JsValue) -> Self {
644            if js_value.is_null() || js_value.is_undefined() {
645                LoroValue::Null
646            } else if js_value.as_bool().is_some() {
647                LoroValue::Bool(js_value.as_bool().unwrap())
648            } else if js_value.as_f64().is_some() {
649                let num = js_value.as_f64().unwrap();
650                if num.fract() == 0.0 && num <= i64::MAX as f64 && num >= i64::MIN as f64 {
651                    LoroValue::I64(num as i64)
652                } else {
653                    LoroValue::Double(num)
654                }
655            } else if js_value.is_string() {
656                LoroValue::String(js_value.as_string().unwrap().into())
657            } else if js_value.has_type::<Array>() {
658                let array = js_value.unchecked_into::<Array>();
659                let mut list = Vec::new();
660                for i in 0..array.length() {
661                    list.push(LoroValue::from(array.get(i)));
662                }
663
664                LoroValue::List(list.into())
665            } else if js_value.is_instance_of::<Uint8Array>() {
666                let array = js_value.unchecked_into::<Uint8Array>();
667                let mut binary = Vec::new();
668                for i in 0..array.length() {
669                    binary.push(array.get_index(i));
670                }
671
672                LoroValue::Binary(binary.into())
673            } else if js_value.is_object() {
674                let object = js_value.unchecked_into::<Object>();
675                let mut map = FxHashMap::default();
676                for key in js_sys::Reflect::own_keys(&object).unwrap().iter() {
677                    let key = key.as_string().unwrap();
678                    map.insert(
679                        key.clone(),
680                        LoroValue::from(js_sys::Reflect::get(&object, &key.into()).unwrap()),
681                    );
682                }
683
684                LoroValue::Map(map.into())
685            } else {
686                panic!("Fail to convert JsValue {js_value:?} to LoroValue ")
687            }
688        }
689    }
690
691    impl From<&ContainerID> for JsValue {
692        fn from(id: &ContainerID) -> Self {
693            JsValue::from_str(id.to_string().as_str())
694        }
695    }
696
697    impl TryFrom<JsValue> for ContainerID {
698        type Error = LoroError;
699
700        fn try_from(value: JsValue) -> Result<Self, Self::Error> {
701            if !value.is_string() {
702                return Err(LoroError::DecodeError(
703                    "Given ContainerId is not string".into(),
704                ));
705            }
706
707            let s = value.as_string().unwrap();
708            ContainerID::try_from(s.as_str()).map_err(|_| {
709                LoroError::DecodeError(
710                    format!("Given ContainerId is not a valid ContainerID: {s}").into(),
711                )
712            })
713        }
714    }
715}
716
717const LORO_CONTAINER_ID_PREFIX: &str = "🦜:";
718
719impl Serialize for LoroValue {
720    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
721    where
722        S: serde::Serializer,
723    {
724        if serializer.is_human_readable() {
725            // json type
726            match self {
727                LoroValue::Null => serializer.serialize_unit(),
728                LoroValue::Bool(b) => serializer.serialize_bool(*b),
729                LoroValue::Double(d) => serializer.serialize_f64(*d),
730                LoroValue::I64(i) => serializer.serialize_i64(*i),
731                LoroValue::String(s) => serializer.serialize_str(s),
732                LoroValue::Binary(b) => serializer.collect_seq(b.iter()),
733                LoroValue::List(l) => serializer.collect_seq(l.iter()),
734                LoroValue::Map(m) => serializer.collect_map(m.iter()),
735                LoroValue::Container(id) => {
736                    serializer.serialize_str(&format!("{LORO_CONTAINER_ID_PREFIX}{id}"))
737                }
738            }
739        } else {
740            // binary type
741            match self {
742                LoroValue::Null => serializer.serialize_unit_variant("LoroValue", 0, "Null"),
743                LoroValue::Bool(b) => {
744                    serializer.serialize_newtype_variant("LoroValue", 1, "Bool", b)
745                }
746                LoroValue::Double(d) => {
747                    serializer.serialize_newtype_variant("LoroValue", 2, "Double", d)
748                }
749                LoroValue::I64(i) => serializer.serialize_newtype_variant("LoroValue", 3, "I32", i),
750                LoroValue::String(s) => {
751                    serializer.serialize_newtype_variant("LoroValue", 4, "String", &**s)
752                }
753
754                LoroValue::List(l) => {
755                    serializer.serialize_newtype_variant("LoroValue", 5, "List", &**l)
756                }
757                LoroValue::Map(m) => {
758                    serializer.serialize_newtype_variant("LoroValue", 6, "Map", &**m)
759                }
760                LoroValue::Container(id) => {
761                    serializer.serialize_newtype_variant("LoroValue", 7, "Container", id)
762                }
763                LoroValue::Binary(b) => {
764                    serializer.serialize_newtype_variant("LoroValue", 8, "Binary", &**b)
765                }
766            }
767        }
768    }
769}
770
771impl<'de> Deserialize<'de> for LoroValue {
772    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
773    where
774        D: serde::Deserializer<'de>,
775    {
776        if deserializer.is_human_readable() {
777            deserializer.deserialize_any(LoroValueVisitor)
778        } else {
779            deserializer.deserialize_enum(
780                "LoroValue",
781                &[
782                    "Null",
783                    "Bool",
784                    "Double",
785                    "I32",
786                    "String",
787                    "List",
788                    "Map",
789                    "Container",
790                    "Binary",
791                ],
792                LoroValueEnumVisitor,
793            )
794        }
795    }
796}
797
798struct LoroValueVisitor;
799
800impl<'de> serde::de::Visitor<'de> for LoroValueVisitor {
801    type Value = LoroValue;
802
803    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
804        formatter.write_str("a LoroValue")
805    }
806
807    fn visit_unit<E>(self) -> Result<Self::Value, E>
808    where
809        E: serde::de::Error,
810    {
811        Ok(LoroValue::Null)
812    }
813
814    fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
815    where
816        E: serde::de::Error,
817    {
818        Ok(LoroValue::Bool(v))
819    }
820
821    fn visit_i64<E>(self, v: i64) -> Result<Self::Value, E>
822    where
823        E: serde::de::Error,
824    {
825        Ok(LoroValue::I64(v))
826    }
827
828    fn visit_u64<E>(self, v: u64) -> Result<Self::Value, E>
829    where
830        E: serde::de::Error,
831    {
832        Ok(i64::try_from(v)
833            .map(LoroValue::I64)
834            .unwrap_or_else(|_| LoroValue::Double(v as f64)))
835    }
836
837    fn visit_f64<E>(self, v: f64) -> Result<Self::Value, E>
838    where
839        E: serde::de::Error,
840    {
841        Ok(LoroValue::Double(v))
842    }
843
844    fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
845    where
846        E: serde::de::Error,
847    {
848        if let Some(id) = v.strip_prefix(LORO_CONTAINER_ID_PREFIX) {
849            return Ok(LoroValue::Container(
850                ContainerID::try_from(id)
851                    .map_err(|_| serde::de::Error::custom("Invalid container id"))?,
852            ));
853        }
854        Ok(LoroValue::String(v.to_owned().into()))
855    }
856
857    fn visit_string<E>(self, v: String) -> Result<Self::Value, E>
858    where
859        E: serde::de::Error,
860    {
861        if let Some(id) = v.strip_prefix(LORO_CONTAINER_ID_PREFIX) {
862            return Ok(LoroValue::Container(
863                ContainerID::try_from(id)
864                    .map_err(|_| serde::de::Error::custom("Invalid container id"))?,
865            ));
866        }
867
868        Ok(LoroValue::String(v.into()))
869    }
870
871    fn visit_borrowed_bytes<E>(self, v: &'de [u8]) -> Result<Self::Value, E>
872    where
873        E: serde::de::Error,
874    {
875        let binary = Vec::from_iter(v.iter().copied());
876        Ok(LoroValue::Binary(binary.into()))
877    }
878
879    fn visit_bytes<E>(self, v: &[u8]) -> Result<Self::Value, E>
880    where
881        E: serde::de::Error,
882    {
883        let binary = Vec::from_iter(v.iter().copied());
884        Ok(LoroValue::Binary(binary.into()))
885    }
886
887    fn visit_seq<A>(self, mut seq: A) -> Result<Self::Value, A::Error>
888    where
889        A: serde::de::SeqAccess<'de>,
890    {
891        let mut list = Vec::new();
892        while let Some(value) = seq.next_element()? {
893            list.push(value);
894        }
895        Ok(LoroValue::List(list.into()))
896    }
897
898    fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
899    where
900        A: serde::de::MapAccess<'de>,
901    {
902        let mut ans: FxHashMap<String, _> = FxHashMap::default();
903        while let Some((key, value)) = map.next_entry::<String, _>()? {
904            ans.insert(key, value);
905        }
906
907        Ok(LoroValue::Map(ans.into()))
908    }
909}
910
911#[derive(Deserialize)]
912enum LoroValueFields {
913    Null,
914    Bool,
915    Double,
916    I32,
917    String,
918    List,
919    Map,
920    Container,
921    Binary,
922}
923
924struct LoroValueEnumVisitor;
925impl<'de> serde::de::Visitor<'de> for LoroValueEnumVisitor {
926    type Value = LoroValue;
927    fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result {
928        formatter.write_str("a loro value")
929    }
930
931    fn visit_enum<A>(self, data: A) -> Result<Self::Value, A::Error>
932    where
933        A: serde::de::EnumAccess<'de>,
934    {
935        match data.variant()? {
936            (LoroValueFields::Null, v) => {
937                v.unit_variant()?;
938                Ok(LoroValue::Null)
939            }
940            (LoroValueFields::Bool, v) => v.newtype_variant().map(LoroValue::Bool),
941            (LoroValueFields::Double, v) => v.newtype_variant().map(LoroValue::Double),
942            (LoroValueFields::I32, v) => v.newtype_variant().map(LoroValue::I64),
943            (LoroValueFields::String, v) => v
944                .newtype_variant()
945                .map(|x: String| LoroValue::String(x.into())),
946            (LoroValueFields::List, v) => v
947                .newtype_variant()
948                .map(|x: Vec<LoroValue>| LoroValue::List(x.into())),
949            (LoroValueFields::Map, v) => v
950                .newtype_variant()
951                .map(|x: FxHashMap<String, LoroValue>| LoroValue::Map(x.into())),
952            (LoroValueFields::Container, v) => v.newtype_variant().map(LoroValue::Container),
953            (LoroValueFields::Binary, v) => v
954                .newtype_variant()
955                .map(|x: Vec<u8>| LoroValue::Binary(x.into())),
956        }
957    }
958}
959
960pub fn to_value<T: Into<LoroValue>>(value: T) -> LoroValue {
961    value.into()
962}
963
964#[cfg(feature = "serde_json")]
965mod serde_json_impl {
966    use serde_json::{Number, Value};
967
968    use super::LoroValue;
969
970    impl From<Value> for LoroValue {
971        fn from(value: Value) -> Self {
972            match value {
973                Value::Null => LoroValue::Null,
974                Value::Bool(b) => LoroValue::Bool(b),
975                Value::Number(n) => {
976                    if let Some(i) = n.as_i64() {
977                        LoroValue::I64(i)
978                    } else {
979                        LoroValue::Double(n.as_f64().unwrap())
980                    }
981                }
982                Value::String(s) => LoroValue::String(s.into()),
983                Value::Array(arr) => {
984                    LoroValue::List(arr.into_iter().map(LoroValue::from).collect())
985                }
986                Value::Object(obj) => LoroValue::Map(
987                    obj.into_iter()
988                        .map(|(k, v)| (k, LoroValue::from(v)))
989                        .collect(),
990                ),
991            }
992        }
993    }
994
995    use super::LORO_CONTAINER_ID_PREFIX;
996    impl From<LoroValue> for Value {
997        fn from(value: LoroValue) -> Self {
998            match value {
999                LoroValue::Null => Value::Null,
1000                LoroValue::Bool(b) => Value::Bool(b),
1001                LoroValue::Double(d) => Number::from_f64(d).map_or(Value::Null, Value::Number),
1002                LoroValue::I64(i) => Value::Number(Number::from(i)),
1003                LoroValue::String(s) => Value::String(s.to_string()),
1004                LoroValue::List(l) => Value::Array(l.iter().cloned().map(Value::from).collect()),
1005                LoroValue::Map(m) => Value::Object(
1006                    m.iter()
1007                        .map(|(k, v)| (k.clone(), Value::from(v.clone())))
1008                        .collect(),
1009                ),
1010                LoroValue::Container(id) => {
1011                    Value::String(format!("{LORO_CONTAINER_ID_PREFIX}{id}"))
1012                }
1013                LoroValue::Binary(b) => Value::Array(b.iter().copied().map(Value::from).collect()),
1014            }
1015        }
1016    }
1017}