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#[derive(Debug, Clone, EnumAsInner, Default)]
14pub enum LoroValue {
15 #[default]
16 Null,
17 Bool(bool),
18 Double(f64),
19 I64(i64),
20 Binary(LoroBinaryValue),
22 String(LoroStringValue),
23 List(LoroListValue),
24 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 pub fn is_too_deep(&self) -> bool {
296 self.get_depth() > MAX_DEPTH
297 }
298
299 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 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 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}