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