loro_internal/
handler.rs

1use super::{state::DocState, txn::Transaction};
2use crate::sync::Mutex;
3use crate::{
4    container::{
5        idx::ContainerIdx,
6        list::list_op::{DeleteSpan, DeleteSpanWithId, ListOp},
7        richtext::{richtext_state::PosType, RichtextState, StyleOp, TextStyleInfoFlag},
8    },
9    cursor::{Cursor, Side},
10    delta::{DeltaItem, Meta, StyleMeta, TreeExternalDiff},
11    diff::{diff, diff_impl::UpdateTimeoutError, OperateProxy},
12    event::{Diff, TextDiff, TextDiffItem, TextMeta},
13    op::ListSlice,
14    state::{IndexType, State, TreeParentId},
15    txn::EventHint,
16    utils::{string_slice::StringSlice, utf16::count_utf16_len},
17    LoroDoc, LoroDocInner,
18};
19use append_only_bytes::BytesSlice;
20use enum_as_inner::EnumAsInner;
21use fxhash::FxHashMap;
22use generic_btree::rle::HasLength;
23use loro_common::{
24    ContainerID, ContainerType, IdFull, InternalString, LoroError, LoroResult, LoroValue, PeerID,
25    TreeID, ID,
26};
27use serde::{Deserialize, Serialize};
28use std::{borrow::Cow, cmp::Reverse, collections::BinaryHeap, fmt::Debug, ops::Deref, sync::Arc};
29use tracing::{error, instrument};
30
31pub use crate::diff::diff_impl::UpdateOptions;
32pub use tree::TreeHandler;
33mod movable_list_apply_delta;
34mod tree;
35
36const INSERT_CONTAINER_VALUE_ARG_ERROR: &str =
37    "Cannot insert a LoroValue::Container directly. To create child container, use insert_container";
38
39mod text_update;
40
41pub trait HandlerTrait: Clone + Sized {
42    fn is_attached(&self) -> bool;
43    fn attached_handler(&self) -> Option<&BasicHandler>;
44    fn get_value(&self) -> LoroValue;
45    fn get_deep_value(&self) -> LoroValue;
46    fn kind(&self) -> ContainerType;
47    fn to_handler(&self) -> Handler;
48    fn from_handler(h: Handler) -> Option<Self>;
49    fn doc(&self) -> Option<LoroDoc>;
50    /// This method returns an attached handler.
51    fn attach(
52        &self,
53        txn: &mut Transaction,
54        parent: &BasicHandler,
55        self_id: ContainerID,
56    ) -> LoroResult<Self>;
57    /// If a detached container is attached, this method will return its corresponding attached handler.
58    fn get_attached(&self) -> Option<Self>;
59
60    fn parent(&self) -> Option<Handler> {
61        self.attached_handler().and_then(|x| x.parent())
62    }
63
64    fn idx(&self) -> ContainerIdx {
65        self.attached_handler()
66            .map(|x| x.container_idx)
67            .unwrap_or_else(|| ContainerIdx::from_index_and_type(u32::MAX, self.kind()))
68    }
69
70    fn id(&self) -> ContainerID {
71        self.attached_handler()
72            .map(|x| x.id.clone())
73            .unwrap_or_else(|| ContainerID::new_normal(ID::NONE_ID, self.kind()))
74    }
75
76    fn with_state<R>(&self, f: impl FnOnce(&mut State) -> LoroResult<R>) -> LoroResult<R> {
77        let inner = self
78            .attached_handler()
79            .ok_or(LoroError::MisuseDetachedContainer {
80                method: "with_state",
81            })?;
82        let state = inner.doc.state.clone();
83        let mut guard = state.lock().unwrap();
84        guard.with_state_mut(inner.container_idx, f)
85    }
86}
87
88fn create_handler(inner: &BasicHandler, id: ContainerID) -> Handler {
89    Handler::new_attached(id, inner.doc.clone())
90}
91
92/// Flatten attributes that allow overlap
93#[derive(Clone, Debug)]
94pub struct BasicHandler {
95    id: ContainerID,
96    container_idx: ContainerIdx,
97    doc: LoroDoc,
98}
99
100struct DetachedInner<T> {
101    value: T,
102    /// If the handler attached later, this field will be filled.
103    attached: Option<BasicHandler>,
104}
105
106impl<T> DetachedInner<T> {
107    fn new(v: T) -> Self {
108        Self {
109            value: v,
110            attached: None,
111        }
112    }
113}
114
115enum MaybeDetached<T> {
116    Detached(Arc<Mutex<DetachedInner<T>>>),
117    Attached(BasicHandler),
118}
119
120impl<T> Clone for MaybeDetached<T> {
121    fn clone(&self) -> Self {
122        match self {
123            MaybeDetached::Detached(a) => MaybeDetached::Detached(Arc::clone(a)),
124            MaybeDetached::Attached(a) => MaybeDetached::Attached(a.clone()),
125        }
126    }
127}
128
129impl<T> MaybeDetached<T> {
130    fn new_detached(v: T) -> Self {
131        MaybeDetached::Detached(Arc::new(Mutex::new(DetachedInner::new(v))))
132    }
133
134    fn is_attached(&self) -> bool {
135        match self {
136            MaybeDetached::Detached(_) => false,
137            MaybeDetached::Attached(_) => true,
138        }
139    }
140
141    fn attached_handler(&self) -> Option<&BasicHandler> {
142        match self {
143            MaybeDetached::Detached(_) => None,
144            MaybeDetached::Attached(a) => Some(a),
145        }
146    }
147
148    fn try_attached_state(&self) -> LoroResult<&BasicHandler> {
149        match self {
150            MaybeDetached::Detached(_) => Err(LoroError::MisuseDetachedContainer {
151                method: "inner_state",
152            }),
153            MaybeDetached::Attached(a) => Ok(a),
154        }
155    }
156}
157
158impl<T> From<BasicHandler> for MaybeDetached<T> {
159    fn from(a: BasicHandler) -> Self {
160        MaybeDetached::Attached(a)
161    }
162}
163
164impl BasicHandler {
165    pub(crate) fn doc(&self) -> LoroDoc {
166        self.doc.clone()
167    }
168
169    #[inline]
170    fn with_doc_state<R>(&self, f: impl FnOnce(&mut DocState) -> R) -> R {
171        let state = self.doc.state.clone();
172        let mut guard = state.lock().unwrap();
173        f(&mut guard)
174    }
175
176    fn with_txn<R>(
177        &self,
178        f: impl FnOnce(&mut Transaction) -> Result<R, LoroError>,
179    ) -> Result<R, LoroError> {
180        with_txn(&self.doc, f)
181    }
182
183    fn get_parent(&self) -> Option<Handler> {
184        let parent_idx = self.doc.arena.get_parent(self.container_idx)?;
185        let parent_id = self.doc.arena.get_container_id(parent_idx).unwrap();
186        {
187            let kind = parent_id.container_type();
188            let handler = BasicHandler {
189                container_idx: parent_idx,
190                id: parent_id,
191                doc: self.doc.clone(),
192            };
193
194            Some(match kind {
195                ContainerType::Map => Handler::Map(MapHandler {
196                    inner: handler.into(),
197                }),
198                ContainerType::List => Handler::List(ListHandler {
199                    inner: handler.into(),
200                }),
201                ContainerType::Tree => Handler::Tree(TreeHandler {
202                    inner: handler.into(),
203                }),
204                ContainerType::Text => Handler::Text(TextHandler {
205                    inner: handler.into(),
206                }),
207                ContainerType::MovableList => Handler::MovableList(MovableListHandler {
208                    inner: handler.into(),
209                }),
210                #[cfg(feature = "counter")]
211                ContainerType::Counter => Handler::Counter(counter::CounterHandler {
212                    inner: handler.into(),
213                }),
214                ContainerType::Unknown(_) => unreachable!(),
215            })
216        }
217    }
218
219    pub fn get_value(&self) -> LoroValue {
220        self.doc
221            .state
222            .lock()
223            .unwrap()
224            .get_value_by_idx(self.container_idx)
225    }
226
227    pub fn get_deep_value(&self) -> LoroValue {
228        self.doc
229            .state
230            .lock()
231            .unwrap()
232            .get_container_deep_value(self.container_idx)
233    }
234
235    fn with_state<R>(&self, f: impl FnOnce(&mut State) -> R) -> R {
236        let mut guard = self.doc.state.lock().unwrap();
237        guard.with_state_mut(self.container_idx, f)
238    }
239
240    pub fn parent(&self) -> Option<Handler> {
241        self.get_parent()
242    }
243
244    fn is_deleted(&self) -> bool {
245        self.doc
246            .state
247            .lock()
248            .unwrap()
249            .is_deleted(self.container_idx)
250    }
251}
252
253/// Flatten attributes that allow overlap
254#[derive(Clone)]
255pub struct TextHandler {
256    inner: MaybeDetached<RichtextState>,
257}
258
259impl HandlerTrait for TextHandler {
260    fn to_handler(&self) -> Handler {
261        Handler::Text(self.clone())
262    }
263
264    fn attach(
265        &self,
266        txn: &mut Transaction,
267        parent: &BasicHandler,
268        self_id: ContainerID,
269    ) -> LoroResult<Self> {
270        match &self.inner {
271            MaybeDetached::Detached(t) => {
272                let mut t = t.lock().unwrap();
273                let inner = create_handler(parent, self_id);
274                let text = inner.into_text().unwrap();
275                let mut delta: Vec<TextDelta> = Vec::new();
276                for span in t.value.iter() {
277                    delta.push(TextDelta::Insert {
278                        insert: span.text.to_string(),
279                        attributes: span.attributes.to_option_map(),
280                    });
281                }
282
283                text.apply_delta_with_txn(txn, &delta)?;
284                t.attached = text.attached_handler().cloned();
285                Ok(text)
286            }
287            MaybeDetached::Attached(a) => {
288                let new_inner = create_handler(a, self_id);
289                let ans = new_inner.into_text().unwrap();
290
291                let delta = self.get_delta();
292                ans.apply_delta_with_txn(txn, &delta).unwrap();
293                Ok(ans)
294            }
295        }
296    }
297
298    fn attached_handler(&self) -> Option<&BasicHandler> {
299        self.inner.attached_handler()
300    }
301
302    fn get_value(&self) -> LoroValue {
303        match &self.inner {
304            MaybeDetached::Detached(t) => {
305                let t = t.lock().unwrap();
306                LoroValue::String((t.value.to_string()).into())
307            }
308            MaybeDetached::Attached(a) => a.get_value(),
309        }
310    }
311
312    fn get_deep_value(&self) -> LoroValue {
313        self.get_value()
314    }
315
316    fn is_attached(&self) -> bool {
317        matches!(&self.inner, MaybeDetached::Attached(..))
318    }
319
320    fn kind(&self) -> ContainerType {
321        ContainerType::Text
322    }
323
324    fn get_attached(&self) -> Option<Self> {
325        match &self.inner {
326            MaybeDetached::Detached(d) => d.lock().unwrap().attached.clone().map(|x| Self {
327                inner: MaybeDetached::Attached(x),
328            }),
329            MaybeDetached::Attached(_a) => Some(self.clone()),
330        }
331    }
332
333    fn from_handler(h: Handler) -> Option<Self> {
334        match h {
335            Handler::Text(x) => Some(x),
336            _ => None,
337        }
338    }
339
340    fn doc(&self) -> Option<LoroDoc> {
341        match &self.inner {
342            MaybeDetached::Detached(_) => None,
343            MaybeDetached::Attached(a) => Some(a.doc()),
344        }
345    }
346}
347
348impl std::fmt::Debug for TextHandler {
349    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
350        match &self.inner {
351            MaybeDetached::Detached(_) => {
352                write!(f, "TextHandler(Unattached)")
353            }
354            MaybeDetached::Attached(a) => {
355                write!(f, "TextHandler({:?})", &a.id)
356            }
357        }
358    }
359}
360
361#[derive(Debug, Clone, EnumAsInner, Deserialize, Serialize, PartialEq)]
362#[serde(untagged)]
363pub enum TextDelta {
364    Retain {
365        retain: usize,
366        attributes: Option<FxHashMap<String, LoroValue>>,
367    },
368    Insert {
369        insert: String,
370        attributes: Option<FxHashMap<String, LoroValue>>,
371    },
372    Delete {
373        delete: usize,
374    },
375}
376
377impl TextDelta {
378    pub fn from_text_diff<'a>(diff: impl Iterator<Item = &'a TextDiffItem>) -> Vec<TextDelta> {
379        let mut ans = Vec::with_capacity(diff.size_hint().0);
380        for iter in diff {
381            match iter {
382                loro_delta::DeltaItem::Retain { len, attr } => {
383                    ans.push(TextDelta::Retain {
384                        retain: *len,
385                        attributes: if attr.0.is_empty() {
386                            None
387                        } else {
388                            Some(attr.0.clone())
389                        },
390                    });
391                }
392                loro_delta::DeltaItem::Replace {
393                    value,
394                    attr,
395                    delete,
396                } => {
397                    if value.rle_len() > 0 {
398                        ans.push(TextDelta::Insert {
399                            insert: value.to_string(),
400                            attributes: if attr.0.is_empty() {
401                                None
402                            } else {
403                                Some(attr.0.clone())
404                            },
405                        });
406                    }
407                    if *delete > 0 {
408                        ans.push(TextDelta::Delete { delete: *delete });
409                    }
410                }
411            }
412        }
413
414        ans
415    }
416
417    pub fn into_text_diff(vec: impl Iterator<Item = Self>) -> TextDiff {
418        let mut delta = TextDiff::new();
419        for item in vec {
420            match item {
421                TextDelta::Retain { retain, attributes } => {
422                    delta.push_retain(retain, TextMeta(attributes.unwrap_or_default().clone()));
423                }
424                TextDelta::Insert { insert, attributes } => {
425                    delta.push_insert(
426                        StringSlice::from(insert.as_str()),
427                        TextMeta(attributes.unwrap_or_default()),
428                    );
429                }
430                TextDelta::Delete { delete } => {
431                    delta.push_delete(delete);
432                }
433            }
434        }
435
436        delta
437    }
438}
439
440impl From<&DeltaItem<StringSlice, StyleMeta>> for TextDelta {
441    fn from(value: &DeltaItem<StringSlice, StyleMeta>) -> Self {
442        match value {
443            crate::delta::DeltaItem::Retain { retain, attributes } => TextDelta::Retain {
444                retain: *retain,
445                attributes: attributes.to_option_map(),
446            },
447            crate::delta::DeltaItem::Insert { insert, attributes } => TextDelta::Insert {
448                insert: insert.to_string(),
449                attributes: attributes.to_option_map(),
450            },
451            crate::delta::DeltaItem::Delete {
452                delete,
453                attributes: _,
454            } => TextDelta::Delete { delete: *delete },
455        }
456    }
457}
458
459#[derive(Clone)]
460pub struct MapHandler {
461    inner: MaybeDetached<FxHashMap<String, ValueOrHandler>>,
462}
463
464impl HandlerTrait for MapHandler {
465    fn is_attached(&self) -> bool {
466        matches!(&self.inner, MaybeDetached::Attached(..))
467    }
468
469    fn attached_handler(&self) -> Option<&BasicHandler> {
470        match &self.inner {
471            MaybeDetached::Detached(_) => None,
472            MaybeDetached::Attached(a) => Some(a),
473        }
474    }
475
476    fn get_value(&self) -> LoroValue {
477        match &self.inner {
478            MaybeDetached::Detached(m) => {
479                let m = m.lock().unwrap();
480                let mut map = FxHashMap::default();
481                for (k, v) in m.value.iter() {
482                    map.insert(k.to_string(), v.to_value());
483                }
484                LoroValue::Map(map.into())
485            }
486            MaybeDetached::Attached(a) => a.get_value(),
487        }
488    }
489
490    fn get_deep_value(&self) -> LoroValue {
491        match &self.inner {
492            MaybeDetached::Detached(m) => {
493                let m = m.lock().unwrap();
494                let mut map = FxHashMap::default();
495                for (k, v) in m.value.iter() {
496                    map.insert(k.to_string(), v.to_deep_value());
497                }
498                LoroValue::Map(map.into())
499            }
500            MaybeDetached::Attached(a) => a.get_deep_value(),
501        }
502    }
503
504    fn kind(&self) -> ContainerType {
505        ContainerType::Map
506    }
507
508    fn to_handler(&self) -> Handler {
509        Handler::Map(self.clone())
510    }
511
512    fn attach(
513        &self,
514        txn: &mut Transaction,
515        parent: &BasicHandler,
516        self_id: ContainerID,
517    ) -> LoroResult<Self> {
518        match &self.inner {
519            MaybeDetached::Detached(m) => {
520                let mut m = m.lock().unwrap();
521                let inner = create_handler(parent, self_id);
522                let map = inner.into_map().unwrap();
523                for (k, v) in m.value.iter() {
524                    match v {
525                        ValueOrHandler::Value(v) => {
526                            map.insert_with_txn(txn, k, v.clone())?;
527                        }
528                        ValueOrHandler::Handler(h) => {
529                            map.insert_container_with_txn(txn, k, h.clone())?;
530                        }
531                    }
532                }
533                m.attached = map.attached_handler().cloned();
534                Ok(map)
535            }
536            MaybeDetached::Attached(a) => {
537                let new_inner = create_handler(a, self_id);
538                let ans = new_inner.into_map().unwrap();
539
540                for (k, v) in self.get_value().into_map().unwrap().iter() {
541                    if let LoroValue::Container(id) = v {
542                        ans.insert_container_with_txn(txn, k, create_handler(a, id.clone()))
543                            .unwrap();
544                    } else {
545                        ans.insert_with_txn(txn, k, v.clone()).unwrap();
546                    }
547                }
548
549                Ok(ans)
550            }
551        }
552    }
553
554    fn get_attached(&self) -> Option<Self> {
555        match &self.inner {
556            MaybeDetached::Detached(d) => d.lock().unwrap().attached.clone().map(|x| Self {
557                inner: MaybeDetached::Attached(x),
558            }),
559            MaybeDetached::Attached(_a) => Some(self.clone()),
560        }
561    }
562
563    fn from_handler(h: Handler) -> Option<Self> {
564        match h {
565            Handler::Map(x) => Some(x),
566            _ => None,
567        }
568    }
569
570    fn doc(&self) -> Option<LoroDoc> {
571        match &self.inner {
572            MaybeDetached::Detached(_) => None,
573            MaybeDetached::Attached(a) => Some(a.doc()),
574        }
575    }
576}
577
578impl std::fmt::Debug for MapHandler {
579    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
580        match &self.inner {
581            MaybeDetached::Detached(_) => write!(f, "MapHandler Detached"),
582            MaybeDetached::Attached(a) => write!(f, "MapHandler {}", a.id),
583        }
584    }
585}
586
587#[derive(Clone)]
588pub struct ListHandler {
589    inner: MaybeDetached<Vec<ValueOrHandler>>,
590}
591
592#[derive(Clone)]
593pub struct MovableListHandler {
594    inner: MaybeDetached<Vec<ValueOrHandler>>,
595}
596
597impl HandlerTrait for MovableListHandler {
598    fn is_attached(&self) -> bool {
599        matches!(&self.inner, MaybeDetached::Attached(..))
600    }
601
602    fn attached_handler(&self) -> Option<&BasicHandler> {
603        match &self.inner {
604            MaybeDetached::Detached(_) => None,
605            MaybeDetached::Attached(a) => Some(a),
606        }
607    }
608
609    fn get_value(&self) -> LoroValue {
610        match &self.inner {
611            MaybeDetached::Detached(a) => {
612                let a = a.lock().unwrap();
613                LoroValue::List(a.value.iter().map(|v| v.to_value()).collect())
614            }
615            MaybeDetached::Attached(a) => a.get_value(),
616        }
617    }
618
619    fn get_deep_value(&self) -> LoroValue {
620        match &self.inner {
621            MaybeDetached::Detached(a) => {
622                let a = a.lock().unwrap();
623                LoroValue::List(a.value.iter().map(|v| v.to_deep_value()).collect())
624            }
625            MaybeDetached::Attached(a) => a.get_deep_value(),
626        }
627    }
628
629    fn kind(&self) -> ContainerType {
630        ContainerType::MovableList
631    }
632
633    fn to_handler(&self) -> Handler {
634        Handler::MovableList(self.clone())
635    }
636
637    fn from_handler(h: Handler) -> Option<Self> {
638        match h {
639            Handler::MovableList(x) => Some(x),
640            _ => None,
641        }
642    }
643
644    fn attach(
645        &self,
646        txn: &mut Transaction,
647        parent: &BasicHandler,
648        self_id: ContainerID,
649    ) -> LoroResult<Self> {
650        match &self.inner {
651            MaybeDetached::Detached(l) => {
652                let mut l = l.lock().unwrap();
653                let inner = create_handler(parent, self_id);
654                let list = inner.into_movable_list().unwrap();
655                for (index, v) in l.value.iter().enumerate() {
656                    match v {
657                        ValueOrHandler::Value(v) => {
658                            list.insert_with_txn(txn, index, v.clone())?;
659                        }
660                        ValueOrHandler::Handler(h) => {
661                            list.insert_container_with_txn(txn, index, h.clone())?;
662                        }
663                    }
664                }
665                l.attached = list.attached_handler().cloned();
666                Ok(list)
667            }
668            MaybeDetached::Attached(a) => {
669                let new_inner = create_handler(a, self_id);
670                let ans = new_inner.into_movable_list().unwrap();
671
672                for (i, v) in self.get_value().into_list().unwrap().iter().enumerate() {
673                    if let LoroValue::Container(id) = v {
674                        ans.insert_container_with_txn(txn, i, create_handler(a, id.clone()))
675                            .unwrap();
676                    } else {
677                        ans.insert_with_txn(txn, i, v.clone()).unwrap();
678                    }
679                }
680
681                Ok(ans)
682            }
683        }
684    }
685
686    fn get_attached(&self) -> Option<Self> {
687        match &self.inner {
688            MaybeDetached::Detached(d) => d.lock().unwrap().attached.clone().map(|x| Self {
689                inner: MaybeDetached::Attached(x),
690            }),
691            MaybeDetached::Attached(_a) => Some(self.clone()),
692        }
693    }
694
695    fn doc(&self) -> Option<LoroDoc> {
696        match &self.inner {
697            MaybeDetached::Detached(_) => None,
698            MaybeDetached::Attached(a) => Some(a.doc()),
699        }
700    }
701}
702
703impl std::fmt::Debug for MovableListHandler {
704    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
705        write!(f, "MovableListHandler {}", self.id())
706    }
707}
708
709impl std::fmt::Debug for ListHandler {
710    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
711        match &self.inner {
712            MaybeDetached::Detached(_) => write!(f, "ListHandler Detached"),
713            MaybeDetached::Attached(a) => write!(f, "ListHandler {}", a.id),
714        }
715    }
716}
717
718impl HandlerTrait for ListHandler {
719    fn is_attached(&self) -> bool {
720        self.inner.is_attached()
721    }
722
723    fn attached_handler(&self) -> Option<&BasicHandler> {
724        self.inner.attached_handler()
725    }
726
727    fn get_value(&self) -> LoroValue {
728        match &self.inner {
729            MaybeDetached::Detached(a) => {
730                let a = a.lock().unwrap();
731                LoroValue::List(a.value.iter().map(|v| v.to_value()).collect())
732            }
733            MaybeDetached::Attached(a) => a.get_value(),
734        }
735    }
736
737    fn get_deep_value(&self) -> LoroValue {
738        match &self.inner {
739            MaybeDetached::Detached(a) => {
740                let a = a.lock().unwrap();
741                LoroValue::List(a.value.iter().map(|v| v.to_deep_value()).collect())
742            }
743            MaybeDetached::Attached(a) => a.get_deep_value(),
744        }
745    }
746
747    fn kind(&self) -> ContainerType {
748        ContainerType::List
749    }
750
751    fn to_handler(&self) -> Handler {
752        Handler::List(self.clone())
753    }
754
755    fn attach(
756        &self,
757        txn: &mut Transaction,
758        parent: &BasicHandler,
759        self_id: ContainerID,
760    ) -> LoroResult<Self> {
761        match &self.inner {
762            MaybeDetached::Detached(l) => {
763                let mut l = l.lock().unwrap();
764                let inner = create_handler(parent, self_id);
765                let list = inner.into_list().unwrap();
766                for (index, v) in l.value.iter().enumerate() {
767                    match v {
768                        ValueOrHandler::Value(v) => {
769                            list.insert_with_txn(txn, index, v.clone())?;
770                        }
771                        ValueOrHandler::Handler(h) => {
772                            list.insert_container_with_txn(txn, index, h.clone())?;
773                        }
774                    }
775                }
776                l.attached = list.attached_handler().cloned();
777                Ok(list)
778            }
779            MaybeDetached::Attached(a) => {
780                let new_inner = create_handler(a, self_id);
781                let ans = new_inner.into_list().unwrap();
782
783                for (i, v) in self.get_value().into_list().unwrap().iter().enumerate() {
784                    if let LoroValue::Container(id) = v {
785                        ans.insert_container_with_txn(txn, i, create_handler(a, id.clone()))
786                            .unwrap();
787                    } else {
788                        ans.insert_with_txn(txn, i, v.clone()).unwrap();
789                    }
790                }
791
792                Ok(ans)
793            }
794        }
795    }
796
797    fn get_attached(&self) -> Option<Self> {
798        match &self.inner {
799            MaybeDetached::Detached(d) => d.lock().unwrap().attached.clone().map(|x| Self {
800                inner: MaybeDetached::Attached(x),
801            }),
802            MaybeDetached::Attached(_a) => Some(self.clone()),
803        }
804    }
805
806    fn from_handler(h: Handler) -> Option<Self> {
807        match h {
808            Handler::List(x) => Some(x),
809            _ => None,
810        }
811    }
812
813    fn doc(&self) -> Option<LoroDoc> {
814        match &self.inner {
815            MaybeDetached::Detached(_) => None,
816            MaybeDetached::Attached(a) => Some(a.doc()),
817        }
818    }
819}
820
821#[derive(Clone)]
822pub struct UnknownHandler {
823    inner: BasicHandler,
824}
825
826impl Debug for UnknownHandler {
827    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
828        write!(f, "UnknownHandler")
829    }
830}
831
832impl UnknownHandler {
833    pub fn is_deleted(&self) -> bool {
834        self.inner.is_deleted()
835    }
836}
837
838impl HandlerTrait for UnknownHandler {
839    fn is_attached(&self) -> bool {
840        true
841    }
842
843    fn attached_handler(&self) -> Option<&BasicHandler> {
844        Some(&self.inner)
845    }
846
847    fn get_value(&self) -> LoroValue {
848        todo!()
849    }
850
851    fn get_deep_value(&self) -> LoroValue {
852        todo!()
853    }
854
855    fn kind(&self) -> ContainerType {
856        self.inner.id.container_type()
857    }
858
859    fn to_handler(&self) -> Handler {
860        Handler::Unknown(self.clone())
861    }
862
863    fn from_handler(h: Handler) -> Option<Self> {
864        match h {
865            Handler::Unknown(x) => Some(x),
866            _ => None,
867        }
868    }
869
870    fn attach(
871        &self,
872        _txn: &mut Transaction,
873        _parent: &BasicHandler,
874        self_id: ContainerID,
875    ) -> LoroResult<Self> {
876        let new_inner = create_handler(&self.inner, self_id);
877        let ans = new_inner.into_unknown().unwrap();
878        Ok(ans)
879    }
880
881    fn get_attached(&self) -> Option<Self> {
882        Some(self.clone())
883    }
884
885    fn doc(&self) -> Option<LoroDoc> {
886        Some(self.inner.doc())
887    }
888}
889
890#[derive(Clone, EnumAsInner, Debug)]
891pub enum Handler {
892    Text(TextHandler),
893    Map(MapHandler),
894    List(ListHandler),
895    MovableList(MovableListHandler),
896    Tree(TreeHandler),
897    #[cfg(feature = "counter")]
898    Counter(counter::CounterHandler),
899    Unknown(UnknownHandler),
900}
901
902impl HandlerTrait for Handler {
903    fn is_attached(&self) -> bool {
904        match self {
905            Self::Text(x) => x.is_attached(),
906            Self::Map(x) => x.is_attached(),
907            Self::List(x) => x.is_attached(),
908            Self::Tree(x) => x.is_attached(),
909            Self::MovableList(x) => x.is_attached(),
910            #[cfg(feature = "counter")]
911            Self::Counter(x) => x.is_attached(),
912            Self::Unknown(x) => x.is_attached(),
913        }
914    }
915
916    fn attached_handler(&self) -> Option<&BasicHandler> {
917        match self {
918            Self::Text(x) => x.attached_handler(),
919            Self::Map(x) => x.attached_handler(),
920            Self::List(x) => x.attached_handler(),
921            Self::MovableList(x) => x.attached_handler(),
922            Self::Tree(x) => x.attached_handler(),
923            #[cfg(feature = "counter")]
924            Self::Counter(x) => x.attached_handler(),
925            Self::Unknown(x) => x.attached_handler(),
926        }
927    }
928
929    fn get_value(&self) -> LoroValue {
930        match self {
931            Self::Text(x) => x.get_value(),
932            Self::Map(x) => x.get_value(),
933            Self::List(x) => x.get_value(),
934            Self::MovableList(x) => x.get_value(),
935            Self::Tree(x) => x.get_value(),
936            #[cfg(feature = "counter")]
937            Self::Counter(x) => x.get_value(),
938            Self::Unknown(x) => x.get_value(),
939        }
940    }
941
942    fn get_deep_value(&self) -> LoroValue {
943        match self {
944            Self::Text(x) => x.get_deep_value(),
945            Self::Map(x) => x.get_deep_value(),
946            Self::List(x) => x.get_deep_value(),
947            Self::MovableList(x) => x.get_deep_value(),
948            Self::Tree(x) => x.get_deep_value(),
949            #[cfg(feature = "counter")]
950            Self::Counter(x) => x.get_deep_value(),
951            Self::Unknown(x) => x.get_deep_value(),
952        }
953    }
954
955    fn kind(&self) -> ContainerType {
956        match self {
957            Self::Text(x) => x.kind(),
958            Self::Map(x) => x.kind(),
959            Self::List(x) => x.kind(),
960            Self::MovableList(x) => x.kind(),
961            Self::Tree(x) => x.kind(),
962            #[cfg(feature = "counter")]
963            Self::Counter(x) => x.kind(),
964            Self::Unknown(x) => x.kind(),
965        }
966    }
967
968    fn to_handler(&self) -> Handler {
969        match self {
970            Self::Text(x) => x.to_handler(),
971            Self::Map(x) => x.to_handler(),
972            Self::List(x) => x.to_handler(),
973            Self::MovableList(x) => x.to_handler(),
974            Self::Tree(x) => x.to_handler(),
975            #[cfg(feature = "counter")]
976            Self::Counter(x) => x.to_handler(),
977            Self::Unknown(x) => x.to_handler(),
978        }
979    }
980
981    fn attach(
982        &self,
983        txn: &mut Transaction,
984        parent: &BasicHandler,
985        self_id: ContainerID,
986    ) -> LoroResult<Self> {
987        match self {
988            Self::Text(x) => Ok(Handler::Text(x.attach(txn, parent, self_id)?)),
989            Self::Map(x) => Ok(Handler::Map(x.attach(txn, parent, self_id)?)),
990            Self::List(x) => Ok(Handler::List(x.attach(txn, parent, self_id)?)),
991            Self::MovableList(x) => Ok(Handler::MovableList(x.attach(txn, parent, self_id)?)),
992            Self::Tree(x) => Ok(Handler::Tree(x.attach(txn, parent, self_id)?)),
993            #[cfg(feature = "counter")]
994            Self::Counter(x) => Ok(Handler::Counter(x.attach(txn, parent, self_id)?)),
995            Self::Unknown(x) => Ok(Handler::Unknown(x.attach(txn, parent, self_id)?)),
996        }
997    }
998
999    fn get_attached(&self) -> Option<Self> {
1000        match self {
1001            Self::Text(x) => x.get_attached().map(Handler::Text),
1002            Self::Map(x) => x.get_attached().map(Handler::Map),
1003            Self::List(x) => x.get_attached().map(Handler::List),
1004            Self::MovableList(x) => x.get_attached().map(Handler::MovableList),
1005            Self::Tree(x) => x.get_attached().map(Handler::Tree),
1006            #[cfg(feature = "counter")]
1007            Self::Counter(x) => x.get_attached().map(Handler::Counter),
1008            Self::Unknown(x) => x.get_attached().map(Handler::Unknown),
1009        }
1010    }
1011
1012    fn from_handler(h: Handler) -> Option<Self> {
1013        Some(h)
1014    }
1015
1016    fn doc(&self) -> Option<LoroDoc> {
1017        match self {
1018            Self::Text(x) => x.doc(),
1019            Self::Map(x) => x.doc(),
1020            Self::List(x) => x.doc(),
1021            Self::MovableList(x) => x.doc(),
1022            Self::Tree(x) => x.doc(),
1023            #[cfg(feature = "counter")]
1024            Self::Counter(x) => x.doc(),
1025            Self::Unknown(x) => x.doc(),
1026        }
1027    }
1028}
1029
1030impl Handler {
1031    pub(crate) fn new_attached(id: ContainerID, doc: LoroDoc) -> Self {
1032        let kind = id.container_type();
1033        let handler = BasicHandler {
1034            container_idx: doc.arena.register_container(&id),
1035            id,
1036            doc,
1037        };
1038
1039        match kind {
1040            ContainerType::Map => Self::Map(MapHandler {
1041                inner: handler.into(),
1042            }),
1043            ContainerType::List => Self::List(ListHandler {
1044                inner: handler.into(),
1045            }),
1046            ContainerType::Tree => Self::Tree(TreeHandler {
1047                inner: handler.into(),
1048            }),
1049            ContainerType::Text => Self::Text(TextHandler {
1050                inner: handler.into(),
1051            }),
1052            ContainerType::MovableList => Self::MovableList(MovableListHandler {
1053                inner: handler.into(),
1054            }),
1055            #[cfg(feature = "counter")]
1056            ContainerType::Counter => Self::Counter(counter::CounterHandler {
1057                inner: handler.into(),
1058            }),
1059            ContainerType::Unknown(_) => Self::Unknown(UnknownHandler { inner: handler }),
1060        }
1061    }
1062
1063    #[allow(unused)]
1064    pub(crate) fn new_unattached(kind: ContainerType) -> Self {
1065        match kind {
1066            ContainerType::Text => Self::Text(TextHandler::new_detached()),
1067            ContainerType::Map => Self::Map(MapHandler::new_detached()),
1068            ContainerType::List => Self::List(ListHandler::new_detached()),
1069            ContainerType::Tree => Self::Tree(TreeHandler::new_detached()),
1070            ContainerType::MovableList => Self::MovableList(MovableListHandler::new_detached()),
1071            #[cfg(feature = "counter")]
1072            ContainerType::Counter => Self::Counter(counter::CounterHandler::new_detached()),
1073            ContainerType::Unknown(_) => unreachable!(),
1074        }
1075    }
1076
1077    pub fn id(&self) -> ContainerID {
1078        match self {
1079            Self::Map(x) => x.id(),
1080            Self::List(x) => x.id(),
1081            Self::Text(x) => x.id(),
1082            Self::Tree(x) => x.id(),
1083            Self::MovableList(x) => x.id(),
1084            #[cfg(feature = "counter")]
1085            Self::Counter(x) => x.id(),
1086            Self::Unknown(x) => x.id(),
1087        }
1088    }
1089
1090    pub(crate) fn container_idx(&self) -> ContainerIdx {
1091        match self {
1092            Self::Map(x) => x.idx(),
1093            Self::List(x) => x.idx(),
1094            Self::Text(x) => x.idx(),
1095            Self::Tree(x) => x.idx(),
1096            Self::MovableList(x) => x.idx(),
1097            #[cfg(feature = "counter")]
1098            Self::Counter(x) => x.idx(),
1099            Self::Unknown(x) => x.idx(),
1100        }
1101    }
1102
1103    pub fn c_type(&self) -> ContainerType {
1104        match self {
1105            Self::Map(_) => ContainerType::Map,
1106            Self::List(_) => ContainerType::List,
1107            Self::Text(_) => ContainerType::Text,
1108            Self::Tree(_) => ContainerType::Tree,
1109            Self::MovableList(_) => ContainerType::MovableList,
1110            #[cfg(feature = "counter")]
1111            Self::Counter(_) => ContainerType::Counter,
1112            Self::Unknown(x) => x.id().container_type(),
1113        }
1114    }
1115
1116    fn get_deep_value(&self) -> LoroValue {
1117        match self {
1118            Self::Map(x) => x.get_deep_value(),
1119            Self::List(x) => x.get_deep_value(),
1120            Self::MovableList(x) => x.get_deep_value(),
1121            Self::Text(x) => x.get_deep_value(),
1122            Self::Tree(x) => x.get_deep_value(),
1123            #[cfg(feature = "counter")]
1124            Self::Counter(x) => x.get_deep_value(),
1125            Self::Unknown(x) => x.get_deep_value(),
1126        }
1127    }
1128
1129    pub(crate) fn apply_diff(
1130        &self,
1131        diff: Diff,
1132        container_remap: &mut FxHashMap<ContainerID, ContainerID>,
1133    ) -> LoroResult<()> {
1134        // In this method we will not clone the values of the containers if
1135        // they are remapped. It's the caller's duty to do so
1136        let on_container_remap = &mut |old_id, new_id| {
1137            container_remap.insert(old_id, new_id);
1138        };
1139        match self {
1140            Self::Map(x) => {
1141                let diff = diff.into_map().unwrap();
1142                for (key, value) in diff.updated.into_iter() {
1143                    match value.value {
1144                        Some(ValueOrHandler::Handler(h)) => {
1145                            let old_id = h.id();
1146                            let new_h = x.insert_container(
1147                                &key,
1148                                Handler::new_unattached(old_id.container_type()),
1149                            )?;
1150                            let new_id = new_h.id();
1151                            on_container_remap(old_id, new_id);
1152                        }
1153                        Some(ValueOrHandler::Value(LoroValue::Container(old_id))) => {
1154                            let new_h = x.insert_container(
1155                                &key,
1156                                Handler::new_unattached(old_id.container_type()),
1157                            )?;
1158                            let new_id = new_h.id();
1159                            on_container_remap(old_id, new_id);
1160                        }
1161                        Some(ValueOrHandler::Value(v)) => {
1162                            x.insert_without_skipping(&key, v)?;
1163                        }
1164                        None => {
1165                            x.delete(&key)?;
1166                        }
1167                    }
1168                }
1169            }
1170            Self::Text(x) => {
1171                let delta = diff.into_text().unwrap();
1172                x.apply_delta(&TextDelta::from_text_diff(delta.iter()))?;
1173            }
1174            Self::List(x) => {
1175                let delta = diff.into_list().unwrap();
1176                x.apply_delta(delta, on_container_remap)?;
1177            }
1178            Self::MovableList(x) => {
1179                let delta = diff.into_list().unwrap();
1180                x.apply_delta(delta, container_remap)?;
1181            }
1182            Self::Tree(x) => {
1183                fn remap_tree_id(
1184                    id: &mut TreeID,
1185                    container_remap: &FxHashMap<ContainerID, ContainerID>,
1186                ) {
1187                    let mut remapped = false;
1188                    let mut map_id = id.associated_meta_container();
1189                    while let Some(rid) = container_remap.get(&map_id) {
1190                        remapped = true;
1191                        map_id = rid.clone();
1192                    }
1193                    if remapped {
1194                        *id = TreeID::new(
1195                            *map_id.as_normal().unwrap().0,
1196                            *map_id.as_normal().unwrap().1,
1197                        )
1198                    }
1199                }
1200                for diff in diff.into_tree().unwrap().diff {
1201                    let mut target = diff.target;
1202                    match diff.action {
1203                        TreeExternalDiff::Create {
1204                            mut parent,
1205                            index: _,
1206                            position,
1207                        } => {
1208                            if let TreeParentId::Node(p) = &mut parent {
1209                                remap_tree_id(p, container_remap)
1210                            }
1211                            remap_tree_id(&mut target, container_remap);
1212                            if !x.is_node_unexist(&target) && !x.is_node_deleted(&target)? {
1213                                // 1@0 is the parent of 2@1
1214                                // ┌────┐    ┌───────────────┐
1215                                // │xxxx│◀───│Move 2@1 to 0@0◀┐
1216                                // └────┘    └───────────────┘│
1217                                // ┌───────┐                  │ ┌────────┐
1218                                // │Del 1@0│◀─────────────────┴─│Meta 2@1│ ◀───  undo 2 ops redo 2 ops
1219                                // └───────┘                    └────────┘
1220                                //
1221                                // When we undo the delete operation, we should not create a new tree node and its child.
1222                                // However, the concurrent operation has moved the child to another parent. It's still alive.
1223                                // So when we redo the delete operation, we should check if the target is still alive.
1224                                // If it's alive, we should move it back instead of creating new one.
1225                                x.move_at_with_target_for_apply_diff(parent, position, target)?;
1226                            } else {
1227                                let new_target = x.__internal__next_tree_id();
1228                                if x.create_at_with_target_for_apply_diff(
1229                                    parent, position, new_target,
1230                                )? {
1231                                    container_remap.insert(
1232                                        target.associated_meta_container(),
1233                                        new_target.associated_meta_container(),
1234                                    );
1235                                }
1236                            }
1237                        }
1238                        TreeExternalDiff::Move {
1239                            mut parent,
1240                            index: _,
1241                            position,
1242                            old_parent: _,
1243                            old_index: _,
1244                        } => {
1245                            if let TreeParentId::Node(p) = &mut parent {
1246                                remap_tree_id(p, container_remap)
1247                            }
1248                            remap_tree_id(&mut target, container_remap);
1249                            // determine if the target is deleted
1250                            if x.is_node_unexist(&target) || x.is_node_deleted(&target).unwrap() {
1251                                // create the target node, we should use the new target id
1252                                let new_target = x.__internal__next_tree_id();
1253                                if x.create_at_with_target_for_apply_diff(
1254                                    parent, position, new_target,
1255                                )? {
1256                                    container_remap.insert(
1257                                        target.associated_meta_container(),
1258                                        new_target.associated_meta_container(),
1259                                    );
1260                                }
1261                            } else {
1262                                x.move_at_with_target_for_apply_diff(parent, position, target)?;
1263                            }
1264                        }
1265                        TreeExternalDiff::Delete { .. } => {
1266                            remap_tree_id(&mut target, container_remap);
1267                            if !x.is_node_deleted(&target).unwrap() {
1268                                x.delete(target)?;
1269                            }
1270                        }
1271                    }
1272                }
1273            }
1274            #[cfg(feature = "counter")]
1275            Self::Counter(x) => {
1276                let delta = diff.into_counter().unwrap();
1277                x.increment(delta)?;
1278            }
1279            Self::Unknown(_) => {
1280                // do nothing
1281            }
1282        }
1283
1284        Ok(())
1285    }
1286
1287    pub fn clear(&self) -> LoroResult<()> {
1288        match self {
1289            Handler::Text(text_handler) => text_handler.clear(),
1290            Handler::Map(map_handler) => map_handler.clear(),
1291            Handler::List(list_handler) => list_handler.clear(),
1292            Handler::MovableList(movable_list_handler) => movable_list_handler.clear(),
1293            Handler::Tree(tree_handler) => tree_handler.clear(),
1294            #[cfg(feature = "counter")]
1295            Handler::Counter(counter_handler) => counter_handler.clear(),
1296            Handler::Unknown(_unknown_handler) => Ok(()),
1297        }
1298    }
1299}
1300
1301#[derive(Clone, EnumAsInner, Debug)]
1302pub enum ValueOrHandler {
1303    Value(LoroValue),
1304    Handler(Handler),
1305}
1306
1307impl ValueOrHandler {
1308    pub(crate) fn from_value(value: LoroValue, doc: &Arc<LoroDocInner>) -> Self {
1309        if let LoroValue::Container(c) = value {
1310            ValueOrHandler::Handler(Handler::new_attached(c, LoroDoc::from_inner(doc.clone())))
1311        } else {
1312            ValueOrHandler::Value(value)
1313        }
1314    }
1315
1316    pub(crate) fn to_value(&self) -> LoroValue {
1317        match self {
1318            Self::Value(v) => v.clone(),
1319            Self::Handler(h) => LoroValue::Container(h.id().clone()),
1320        }
1321    }
1322
1323    pub(crate) fn to_deep_value(&self) -> LoroValue {
1324        match self {
1325            Self::Value(v) => v.clone(),
1326            Self::Handler(h) => h.get_deep_value(),
1327        }
1328    }
1329}
1330
1331impl From<LoroValue> for ValueOrHandler {
1332    fn from(value: LoroValue) -> Self {
1333        ValueOrHandler::Value(value)
1334    }
1335}
1336
1337impl TextHandler {
1338    /// Create a new container that is detached from the document.
1339    ///
1340    /// The edits on a detached container will not be persisted.
1341    /// To attach the container to the document, please insert it into an attached container.
1342    pub fn new_detached() -> Self {
1343        Self {
1344            inner: MaybeDetached::new_detached(RichtextState::default()),
1345        }
1346    }
1347
1348    /// Get the version id of the richtext
1349    ///
1350    /// This can be used to detect whether the richtext is changed
1351    pub fn version_id(&self) -> Option<usize> {
1352        match &self.inner {
1353            MaybeDetached::Detached(_) => None,
1354            MaybeDetached::Attached(a) => {
1355                Some(a.with_state(|state| state.as_richtext_state_mut().unwrap().get_version_id()))
1356            }
1357        }
1358    }
1359
1360    pub fn get_richtext_value(&self) -> LoroValue {
1361        match &self.inner {
1362            MaybeDetached::Detached(t) => {
1363                let t = t.lock().unwrap();
1364                t.value.get_richtext_value()
1365            }
1366            MaybeDetached::Attached(a) => {
1367                a.with_state(|state| state.as_richtext_state_mut().unwrap().get_richtext_value())
1368            }
1369        }
1370    }
1371
1372    pub fn is_empty(&self) -> bool {
1373        match &self.inner {
1374            MaybeDetached::Detached(t) => t.lock().unwrap().value.is_empty(),
1375            MaybeDetached::Attached(a) => {
1376                a.with_state(|state| state.as_richtext_state_mut().unwrap().is_empty())
1377            }
1378        }
1379    }
1380
1381    pub fn len_utf8(&self) -> usize {
1382        match &self.inner {
1383            MaybeDetached::Detached(t) => {
1384                let t = t.lock().unwrap();
1385                t.value.len_utf8()
1386            }
1387            MaybeDetached::Attached(a) => {
1388                a.with_state(|state| state.as_richtext_state_mut().unwrap().len_utf8())
1389            }
1390        }
1391    }
1392
1393    pub fn len_utf16(&self) -> usize {
1394        match &self.inner {
1395            MaybeDetached::Detached(t) => {
1396                let t = t.lock().unwrap();
1397                t.value.len_utf16()
1398            }
1399            MaybeDetached::Attached(a) => {
1400                a.with_state(|state| state.as_richtext_state_mut().unwrap().len_utf16())
1401            }
1402        }
1403    }
1404
1405    pub fn len_unicode(&self) -> usize {
1406        match &self.inner {
1407            MaybeDetached::Detached(t) => {
1408                let t = t.lock().unwrap();
1409                t.value.len_unicode()
1410            }
1411            MaybeDetached::Attached(a) => {
1412                a.with_state(|state| state.as_richtext_state_mut().unwrap().len_unicode())
1413            }
1414        }
1415    }
1416
1417    /// if `wasm` feature is enabled, it is a UTF-16 length
1418    /// otherwise, it is a Unicode length
1419    pub fn len_event(&self) -> usize {
1420        if cfg!(feature = "wasm") {
1421            self.len_utf16()
1422        } else {
1423            self.len_unicode()
1424        }
1425    }
1426
1427    pub fn diagnose(&self) {
1428        match &self.inner {
1429            MaybeDetached::Detached(t) => {
1430                let t = t.lock().unwrap();
1431                t.value.diagnose();
1432            }
1433            MaybeDetached::Attached(a) => {
1434                a.with_state(|state| state.as_richtext_state_mut().unwrap().diagnose());
1435            }
1436        }
1437    }
1438
1439    pub fn iter(&self, mut callback: impl FnMut(&str) -> bool) {
1440        match &self.inner {
1441            MaybeDetached::Detached(t) => {
1442                let t = t.lock().unwrap();
1443                for span in t.value.iter() {
1444                    if !callback(span.text.as_str()) {
1445                        return;
1446                    }
1447                }
1448            }
1449            MaybeDetached::Attached(a) => {
1450                a.with_state(|state| {
1451                    state.as_richtext_state_mut().unwrap().iter(callback);
1452                });
1453            }
1454        }
1455    }
1456
1457    /// `pos` is a Event Index:
1458    ///
1459    /// - if feature="wasm", pos is a UTF-16 index
1460    /// - if feature!="wasm", pos is a Unicode index
1461    pub fn char_at(&self, pos: usize) -> LoroResult<char> {
1462        if pos >= self.len_event() {
1463            return Err(LoroError::OutOfBound {
1464                pos,
1465                len: self.len_event(),
1466                info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
1467            });
1468        }
1469        if let Ok(c) = match &self.inner {
1470            MaybeDetached::Detached(t) => {
1471                let t = t.lock().unwrap();
1472                t.value.get_char_by_event_index(pos)
1473            }
1474            MaybeDetached::Attached(a) => a.with_state(|state| {
1475                state
1476                    .as_richtext_state_mut()
1477                    .unwrap()
1478                    .get_char_by_event_index(pos)
1479            }),
1480        } {
1481            Ok(c)
1482        } else {
1483            Err(LoroError::OutOfBound {
1484                pos,
1485                len: self.len_event(),
1486                info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
1487            })
1488        }
1489    }
1490
1491    /// `start_index` and `end_index` are Event Index:
1492    ///
1493    /// - if feature="wasm", pos is a UTF-16 index
1494    /// - if feature!="wasm", pos is a Unicode index
1495    ///
1496    pub fn slice(&self, start_index: usize, end_index: usize) -> LoroResult<String> {
1497        if end_index < start_index {
1498            return Err(LoroError::EndIndexLessThanStartIndex {
1499                start: start_index,
1500                end: end_index,
1501            });
1502        }
1503        match &self.inner {
1504            MaybeDetached::Detached(t) => {
1505                let t = t.lock().unwrap();
1506                t.value
1507                    .get_text_slice_by_event_index(start_index, end_index - start_index)
1508            }
1509            MaybeDetached::Attached(a) => a.with_state(|state| {
1510                state
1511                    .as_richtext_state_mut()
1512                    .unwrap()
1513                    .get_text_slice_by_event_index(start_index, end_index - start_index)
1514            }),
1515        }
1516    }
1517
1518    /// `pos` is a Event Index:
1519    ///
1520    /// - if feature="wasm", pos is a UTF-16 index
1521    /// - if feature!="wasm", pos is a Unicode index
1522    ///
1523    /// This method requires auto_commit to be enabled.
1524    pub fn splice(&self, pos: usize, len: usize, s: &str) -> LoroResult<String> {
1525        let x = self.slice(pos, pos + len)?;
1526        self.delete(pos, len)?;
1527        self.insert(pos, s)?;
1528        Ok(x)
1529    }
1530
1531    pub fn splice_utf8(&self, pos: usize, len: usize, s: &str) -> LoroResult<()> {
1532        // let x = self.slice(pos, pos + len)?;
1533        self.delete_utf8(pos, len)?;
1534        self.insert_utf8(pos, s)?;
1535        Ok(())
1536    }
1537
1538    /// `pos` is a Event Index:
1539    ///
1540    /// - if feature="wasm", pos is a UTF-16 index
1541    /// - if feature!="wasm", pos is a Unicode index
1542    ///
1543    /// This method requires auto_commit to be enabled.
1544    pub fn insert(&self, pos: usize, s: &str) -> LoroResult<()> {
1545        match &self.inner {
1546            MaybeDetached::Detached(t) => {
1547                let mut t = t.lock().unwrap();
1548                let (index, _) = t
1549                    .value
1550                    .get_entity_index_for_text_insert(pos, PosType::Event)
1551                    .unwrap();
1552                t.value.insert_at_entity_index(
1553                    index,
1554                    BytesSlice::from_bytes(s.as_bytes()),
1555                    IdFull::NONE_ID,
1556                );
1557                Ok(())
1558            }
1559            MaybeDetached::Attached(a) => a.with_txn(|txn| self.insert_with_txn(txn, pos, s)),
1560        }
1561    }
1562
1563    pub fn insert_utf8(&self, pos: usize, s: &str) -> LoroResult<()> {
1564        match &self.inner {
1565            MaybeDetached::Detached(t) => {
1566                let mut t = t.lock().unwrap();
1567                let (index, _) = t
1568                    .value
1569                    .get_entity_index_for_text_insert(pos, PosType::Bytes)
1570                    .unwrap();
1571                t.value.insert_at_entity_index(
1572                    index,
1573                    BytesSlice::from_bytes(s.as_bytes()),
1574                    IdFull::NONE_ID,
1575                );
1576                Ok(())
1577            }
1578            MaybeDetached::Attached(a) => a.with_txn(|txn| self.insert_with_txn_utf8(txn, pos, s)),
1579        }
1580    }
1581
1582    pub fn insert_unicode(&self, pos: usize, s: &str) -> LoroResult<()> {
1583        match &self.inner {
1584            MaybeDetached::Detached(t) => {
1585                let mut t = t.lock().unwrap();
1586                let (index, _) = t
1587                    .value
1588                    .get_entity_index_for_text_insert(pos, PosType::Unicode)
1589                    .unwrap();
1590                t.value.insert_at_entity_index(
1591                    index,
1592                    BytesSlice::from_bytes(s.as_bytes()),
1593                    IdFull::NONE_ID,
1594                );
1595                Ok(())
1596            }
1597            MaybeDetached::Attached(a) => a.with_txn(|txn| {
1598                self.insert_with_txn_and_attr(txn, pos, s, None, PosType::Unicode)?;
1599                Ok(())
1600            }),
1601        }
1602    }
1603
1604    /// `pos` is a Event Index:
1605    ///
1606    /// - if feature="wasm", pos is a UTF-16 index
1607    /// - if feature!="wasm", pos is a Unicode index
1608    pub fn insert_with_txn(&self, txn: &mut Transaction, pos: usize, s: &str) -> LoroResult<()> {
1609        self.insert_with_txn_and_attr(txn, pos, s, None, PosType::Event)?;
1610        Ok(())
1611    }
1612
1613    pub fn insert_with_txn_utf8(
1614        &self,
1615        txn: &mut Transaction,
1616        pos: usize,
1617        s: &str,
1618    ) -> LoroResult<()> {
1619        self.insert_with_txn_and_attr(txn, pos, s, None, PosType::Bytes)?;
1620        Ok(())
1621    }
1622
1623    /// `pos` is a Event Index:
1624    ///
1625    /// - if feature="wasm", pos is a UTF-16 index
1626    /// - if feature!="wasm", pos is a Unicode index
1627    ///
1628    /// This method requires auto_commit to be enabled.
1629    pub fn delete(&self, pos: usize, len: usize) -> LoroResult<()> {
1630        match &self.inner {
1631            MaybeDetached::Detached(t) => {
1632                let mut t = t.lock().unwrap();
1633                let ranges = t
1634                    .value
1635                    .get_text_entity_ranges(pos, len, PosType::Event)
1636                    .unwrap();
1637                for range in ranges.iter().rev() {
1638                    t.value
1639                        .drain_by_entity_index(range.entity_start, range.entity_len(), None);
1640                }
1641                Ok(())
1642            }
1643            MaybeDetached::Attached(a) => a.with_txn(|txn| self.delete_with_txn(txn, pos, len)),
1644        }
1645    }
1646
1647    pub fn delete_utf8(&self, pos: usize, len: usize) -> LoroResult<()> {
1648        match &self.inner {
1649            MaybeDetached::Detached(t) => {
1650                let mut t = t.lock().unwrap();
1651                let ranges = t.value.get_text_entity_ranges(pos, len, PosType::Bytes)?;
1652                for range in ranges.iter().rev() {
1653                    t.value
1654                        .drain_by_entity_index(range.entity_start, range.entity_len(), None);
1655                }
1656                Ok(())
1657            }
1658            MaybeDetached::Attached(a) => {
1659                a.with_txn(|txn| self.delete_with_txn_inline(txn, pos, len, PosType::Bytes))
1660            }
1661        }
1662    }
1663
1664    pub fn delete_unicode(&self, pos: usize, len: usize) -> LoroResult<()> {
1665        match &self.inner {
1666            MaybeDetached::Detached(t) => {
1667                let mut t = t.lock().unwrap();
1668                let ranges = t.value.get_text_entity_ranges(pos, len, PosType::Unicode)?;
1669                for range in ranges.iter().rev() {
1670                    t.value
1671                        .drain_by_entity_index(range.entity_start, range.entity_len(), None);
1672                }
1673                Ok(())
1674            }
1675            MaybeDetached::Attached(a) => {
1676                a.with_txn(|txn| self.delete_with_txn_inline(txn, pos, len, PosType::Unicode))
1677            }
1678        }
1679    }
1680
1681    /// If attr is specified, it will be used as the attribute of the inserted text.
1682    /// It will override the existing attribute of the text.
1683    fn insert_with_txn_and_attr(
1684        &self,
1685        txn: &mut Transaction,
1686        pos: usize,
1687        s: &str,
1688        attr: Option<&FxHashMap<String, LoroValue>>,
1689        pos_type: PosType,
1690    ) -> Result<Vec<(InternalString, LoroValue)>, LoroError> {
1691        if s.is_empty() {
1692            return Ok(Vec::new());
1693        }
1694
1695        match pos_type {
1696            PosType::Event => {
1697                if pos > self.len_event() {
1698                    return Err(LoroError::OutOfBound {
1699                        pos,
1700                        len: self.len_event(),
1701                        info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
1702                    });
1703                }
1704            }
1705            PosType::Bytes => {
1706                if pos > self.len_utf8() {
1707                    return Err(LoroError::OutOfBound {
1708                        pos,
1709                        len: self.len_utf8(),
1710                        info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
1711                    });
1712                }
1713            }
1714            PosType::Unicode => {
1715                if pos > self.len_unicode() {
1716                    return Err(LoroError::OutOfBound {
1717                        pos,
1718                        len: self.len_unicode(),
1719                        info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
1720                    });
1721                }
1722            }
1723            PosType::Entity => {}
1724            PosType::Utf16 => {
1725                if pos > self.len_utf16() {
1726                    return Err(LoroError::OutOfBound {
1727                        pos,
1728                        len: self.len_utf16(),
1729                        info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
1730                    });
1731                }
1732            }
1733        }
1734
1735        let inner = self.inner.try_attached_state()?;
1736        let (entity_index, event_index, styles) = inner.with_state(|state| {
1737            let richtext_state = state.as_richtext_state_mut().unwrap();
1738            let ret = richtext_state.get_entity_index_for_text_insert(pos, pos_type);
1739            let (entity_index, cursor) = match ret {
1740                Err(_) => match pos_type {
1741                    PosType::Bytes => {
1742                        return (
1743                            Err(LoroError::UTF8InUnicodeCodePoint { pos }),
1744                            0,
1745                            StyleMeta::empty(),
1746                        );
1747                    }
1748                    PosType::Utf16 | PosType::Event => {
1749                        return (
1750                            Err(LoroError::UTF16InUnicodeCodePoint { pos }),
1751                            0,
1752                            StyleMeta::empty(),
1753                        );
1754                    }
1755                    _ => unreachable!(),
1756                },
1757                Ok(x) => x,
1758            };
1759            let event_index = if let Some(cursor) = cursor {
1760                if pos_type == PosType::Event {
1761                    debug_assert_eq!(
1762                        richtext_state.get_event_index_by_cursor(cursor),
1763                        pos,
1764                        "pos={} cursor={:?} state={:#?}",
1765                        pos,
1766                        cursor,
1767                        &richtext_state
1768                    );
1769                    pos
1770                } else {
1771                    richtext_state.get_event_index_by_cursor(cursor)
1772                }
1773            } else {
1774                assert_eq!(entity_index, 0);
1775                0
1776            };
1777            let styles = richtext_state.get_styles_at_entity_index(entity_index);
1778            (Ok(entity_index), event_index, styles)
1779        });
1780
1781        let entity_index = match entity_index {
1782            Err(x) => return Err(x),
1783            _ => entity_index.unwrap(),
1784        };
1785
1786        let mut override_styles = Vec::new();
1787        if let Some(attr) = attr {
1788            // current styles
1789            let map: FxHashMap<_, _> = styles.iter().map(|x| (x.0.clone(), x.1.data)).collect();
1790            for (key, style) in map.iter() {
1791                match attr.get(key.deref()) {
1792                    Some(v) if v == style => {}
1793                    new_style_value => {
1794                        // need to override
1795                        let new_style_value = new_style_value.cloned().unwrap_or(LoroValue::Null);
1796                        override_styles.push((key.clone(), new_style_value));
1797                    }
1798                }
1799            }
1800
1801            for (key, style) in attr.iter() {
1802                let key = key.as_str().into();
1803                if !map.contains_key(&key) {
1804                    override_styles.push((key, style.clone()));
1805                }
1806            }
1807        }
1808
1809        let unicode_len = s.chars().count();
1810        let event_len = if cfg!(feature = "wasm") {
1811            count_utf16_len(s.as_bytes())
1812        } else {
1813            unicode_len
1814        };
1815
1816        txn.apply_local_op(
1817            inner.container_idx,
1818            crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Insert {
1819                slice: ListSlice::RawStr {
1820                    str: Cow::Borrowed(s),
1821                    unicode_len,
1822                },
1823                pos: entity_index,
1824            }),
1825            EventHint::InsertText {
1826                pos: event_index as u32,
1827                styles,
1828                unicode_len: unicode_len as u32,
1829                event_len: event_len as u32,
1830            },
1831            &inner.doc,
1832        )?;
1833
1834        Ok(override_styles)
1835    }
1836
1837    /// `pos` is a Event Index:
1838    ///
1839    /// - if feature="wasm", pos is a UTF-16 index
1840    /// - if feature!="wasm", pos is a Unicode index
1841    pub fn delete_with_txn(&self, txn: &mut Transaction, pos: usize, len: usize) -> LoroResult<()> {
1842        self.delete_with_txn_inline(txn, pos, len, PosType::Event)
1843    }
1844
1845    fn delete_with_txn_inline(
1846        &self,
1847        txn: &mut Transaction,
1848        pos: usize,
1849        len: usize,
1850        pos_type: PosType,
1851    ) -> LoroResult<()> {
1852        if len == 0 {
1853            return Ok(());
1854        }
1855
1856        match pos_type {
1857            PosType::Event => {
1858                if pos + len > self.len_event() {
1859                    error!("pos={} len={} len_event={}", pos, len, self.len_event());
1860                    return Err(LoroError::OutOfBound {
1861                        pos: pos + len,
1862                        len: self.len_event(),
1863                        info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
1864                    });
1865                }
1866            }
1867            PosType::Bytes => {
1868                if pos + len > self.len_utf8() {
1869                    error!("pos={} len={} len_bytes={}", pos, len, self.len_utf8());
1870                    return Err(LoroError::OutOfBound {
1871                        pos: pos + len,
1872                        len: self.len_utf8(),
1873                        info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
1874                    });
1875                }
1876            }
1877            _ => (),
1878        }
1879
1880        let inner = self.inner.try_attached_state()?;
1881        let s = tracing::span!(tracing::Level::INFO, "delete", "pos={} len={}", pos, len);
1882        let _e = s.enter();
1883        let mut event_pos = 0;
1884        let mut event_len = 0;
1885        let ranges = inner.with_state(|state| {
1886            let richtext_state = state.as_richtext_state_mut().unwrap();
1887            event_pos = richtext_state.index_to_event_index(pos, pos_type);
1888            let event_end = richtext_state.index_to_event_index(pos + len, pos_type);
1889            event_len = event_end - event_pos;
1890
1891            richtext_state.get_text_entity_ranges_in_event_index_range(event_pos, event_len)
1892        })?;
1893
1894        //debug_assert_eq!(ranges.iter().map(|x| x.event_len).sum::<usize>(), len);
1895        let pos = event_pos as isize;
1896        let len = event_len as isize;
1897        let mut event_end = pos + len;
1898        for range in ranges.iter().rev() {
1899            let event_start = event_end - range.event_len as isize;
1900            txn.apply_local_op(
1901                inner.container_idx,
1902                crate::op::RawOpContent::List(ListOp::Delete(DeleteSpanWithId::new(
1903                    range.id_start,
1904                    range.entity_start as isize,
1905                    range.entity_len() as isize,
1906                ))),
1907                EventHint::DeleteText {
1908                    span: DeleteSpan {
1909                        pos: event_start,
1910                        signed_len: range.event_len as isize,
1911                    },
1912                    unicode_len: range.entity_len(),
1913                },
1914                &inner.doc,
1915            )?;
1916            event_end = event_start;
1917        }
1918
1919        Ok(())
1920    }
1921
1922    /// `start` and `end` are [Event Index]s:
1923    ///
1924    /// - if feature="wasm", pos is a UTF-16 index
1925    /// - if feature!="wasm", pos is a Unicode index
1926    ///
1927    /// This method requires auto_commit to be enabled.
1928    pub fn mark(
1929        &self,
1930        start: usize,
1931        end: usize,
1932        key: impl Into<InternalString>,
1933        value: LoroValue,
1934    ) -> LoroResult<()> {
1935        match &self.inner {
1936            MaybeDetached::Detached(t) => {
1937                let mut g = t.lock().unwrap();
1938                self.mark_for_detached(&mut g.value, key, &value, start, end, false)
1939            }
1940            MaybeDetached::Attached(a) => {
1941                a.with_txn(|txn| self.mark_with_txn(txn, start, end, key, value, false))
1942            }
1943        }
1944    }
1945
1946    fn mark_for_detached(
1947        &self,
1948        state: &mut RichtextState,
1949        key: impl Into<InternalString>,
1950        value: &LoroValue,
1951        start: usize,
1952        end: usize,
1953        is_delete: bool,
1954    ) -> Result<(), LoroError> {
1955        let key: InternalString = key.into();
1956        let len = state.len_event();
1957        if start >= end {
1958            return Err(loro_common::LoroError::ArgErr(
1959                "Start must be less than end".to_string().into_boxed_str(),
1960            ));
1961        }
1962        if end > len {
1963            return Err(LoroError::OutOfBound {
1964                pos: end,
1965                len,
1966                info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
1967            });
1968        }
1969        let (entity_range, styles) =
1970            state.get_entity_range_and_text_styles_at_range(start..end, PosType::Event);
1971        if let Some(styles) = styles {
1972            if styles.has_key_value(&key, value) {
1973                // already has the same style, skip
1974                return Ok(());
1975            }
1976        }
1977
1978        let style_op = Arc::new(StyleOp {
1979            lamport: 0,
1980            peer: 0,
1981            cnt: 0,
1982            key,
1983            value: value.clone(),
1984            // TODO: describe this behavior in the document
1985            info: if is_delete {
1986                TextStyleInfoFlag::BOLD.to_delete()
1987            } else {
1988                TextStyleInfoFlag::BOLD
1989            },
1990        });
1991        state.mark_with_entity_index(entity_range, style_op);
1992        Ok(())
1993    }
1994
1995    /// `start` and `end` are [Event Index]s:
1996    ///
1997    /// - if feature="wasm", pos is a UTF-16 index
1998    /// - if feature!="wasm", pos is a Unicode index
1999    ///
2000    /// This method requires auto_commit to be enabled.
2001    pub fn unmark(
2002        &self,
2003        start: usize,
2004        end: usize,
2005        key: impl Into<InternalString>,
2006    ) -> LoroResult<()> {
2007        match &self.inner {
2008            MaybeDetached::Detached(t) => self.mark_for_detached(
2009                &mut t.lock().unwrap().value,
2010                key,
2011                &LoroValue::Null,
2012                start,
2013                end,
2014                true,
2015            ),
2016            MaybeDetached::Attached(a) => {
2017                a.with_txn(|txn| self.mark_with_txn(txn, start, end, key, LoroValue::Null, true))
2018            }
2019        }
2020    }
2021
2022    /// `start` and `end` are [Event Index]s:
2023    ///
2024    /// - if feature="wasm", pos is a UTF-16 index
2025    /// - if feature!="wasm", pos is a Unicode index
2026    pub fn mark_with_txn(
2027        &self,
2028        txn: &mut Transaction,
2029        start: usize,
2030        end: usize,
2031        key: impl Into<InternalString>,
2032        value: LoroValue,
2033        is_delete: bool,
2034    ) -> LoroResult<()> {
2035        if start >= end {
2036            return Err(loro_common::LoroError::ArgErr(
2037                "Start must be less than end".to_string().into_boxed_str(),
2038            ));
2039        }
2040
2041        let len = self.len_event();
2042        if end > len {
2043            return Err(LoroError::OutOfBound {
2044                pos: end,
2045                len,
2046                info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
2047            });
2048        }
2049
2050        let inner = self.inner.try_attached_state()?;
2051        let key: InternalString = key.into();
2052
2053        let mut doc_state = inner.doc.state.lock().unwrap();
2054        let (entity_range, skip) = doc_state.with_state_mut(inner.container_idx, |state| {
2055            let (entity_range, styles) = state
2056                .as_richtext_state_mut()
2057                .unwrap()
2058                .get_entity_range_and_styles_at_range(start..end, PosType::Event);
2059
2060            let skip = match styles {
2061                Some(styles) if styles.has_key_value(&key, &value) => {
2062                    // already has the same style, skip
2063                    true
2064                }
2065                _ => false,
2066            };
2067            (entity_range, skip)
2068        });
2069
2070        if skip {
2071            return Ok(());
2072        }
2073
2074        let entity_start = entity_range.start;
2075        let entity_end = entity_range.end;
2076        let style_config = doc_state.config.text_style_config.try_read().unwrap();
2077        let flag = if is_delete {
2078            style_config
2079                .get_style_flag_for_unmark(&key)
2080                .ok_or_else(|| LoroError::StyleConfigMissing(key.clone()))?
2081        } else {
2082            style_config
2083                .get_style_flag(&key)
2084                .ok_or_else(|| LoroError::StyleConfigMissing(key.clone()))?
2085        };
2086
2087        drop(style_config);
2088        drop(doc_state);
2089        txn.apply_local_op(
2090            inner.container_idx,
2091            crate::op::RawOpContent::List(ListOp::StyleStart {
2092                start: entity_start as u32,
2093                end: entity_end as u32,
2094                key: key.clone(),
2095                value: value.clone(),
2096                info: flag,
2097            }),
2098            EventHint::Mark {
2099                start: start as u32,
2100                end: end as u32,
2101                style: crate::container::richtext::Style { key, data: value },
2102            },
2103            &inner.doc,
2104        )?;
2105
2106        txn.apply_local_op(
2107            inner.container_idx,
2108            crate::op::RawOpContent::List(ListOp::StyleEnd),
2109            EventHint::MarkEnd,
2110            &inner.doc,
2111        )?;
2112
2113        Ok(())
2114    }
2115
2116    pub fn check(&self) {
2117        match &self.inner {
2118            MaybeDetached::Detached(t) => {
2119                let t = t.lock().unwrap();
2120                t.value.check_consistency_between_content_and_style_ranges();
2121            }
2122            MaybeDetached::Attached(a) => a.with_state(|state| {
2123                state
2124                    .as_richtext_state_mut()
2125                    .unwrap()
2126                    .check_consistency_between_content_and_style_ranges();
2127            }),
2128        }
2129    }
2130
2131    pub fn apply_delta(&self, delta: &[TextDelta]) -> LoroResult<()> {
2132        match &self.inner {
2133            MaybeDetached::Detached(t) => {
2134                let _t = t.lock().unwrap();
2135                // TODO: implement
2136                Err(LoroError::NotImplemented(
2137                    "`apply_delta` on a detached text container",
2138                ))
2139            }
2140            MaybeDetached::Attached(a) => a.with_txn(|txn| self.apply_delta_with_txn(txn, delta)),
2141        }
2142    }
2143
2144    pub fn apply_delta_with_txn(
2145        &self,
2146        txn: &mut Transaction,
2147        delta: &[TextDelta],
2148    ) -> LoroResult<()> {
2149        let mut index = 0;
2150        struct PendingMark {
2151            start: usize,
2152            end: usize,
2153            attributes: FxHashMap<InternalString, LoroValue>,
2154        }
2155        let mut marks: Vec<PendingMark> = Vec::new();
2156        for d in delta {
2157            match d {
2158                TextDelta::Insert { insert, attributes } => {
2159                    let end = index + event_len(insert.as_str());
2160                    let override_styles = self.insert_with_txn_and_attr(
2161                        txn,
2162                        index,
2163                        insert.as_str(),
2164                        Some(attributes.as_ref().unwrap_or(&Default::default())),
2165                        PosType::Event,
2166                    )?;
2167
2168                    let mut pending_mark = PendingMark {
2169                        start: index,
2170                        end,
2171                        attributes: FxHashMap::default(),
2172                    };
2173                    for (key, value) in override_styles {
2174                        pending_mark.attributes.insert(key, value);
2175                    }
2176                    marks.push(pending_mark);
2177                    index = end;
2178                }
2179                TextDelta::Delete { delete } => {
2180                    self.delete_with_txn(txn, index, *delete)?;
2181                }
2182                TextDelta::Retain { attributes, retain } => {
2183                    let end = index + *retain;
2184                    match attributes {
2185                        Some(attr) if !attr.is_empty() => {
2186                            let mut pending_mark = PendingMark {
2187                                start: index,
2188                                end,
2189                                attributes: FxHashMap::default(),
2190                            };
2191                            for (key, value) in attr {
2192                                pending_mark
2193                                    .attributes
2194                                    .insert(key.deref().into(), value.clone());
2195                            }
2196                            marks.push(pending_mark);
2197                        }
2198                        _ => {}
2199                    }
2200                    index = end;
2201                }
2202            }
2203        }
2204
2205        let mut len = self.len_event();
2206        for pending_mark in marks {
2207            if pending_mark.start >= len {
2208                self.insert_with_txn(txn, len, &"\n".repeat(pending_mark.start - len + 1))?;
2209                len = pending_mark.start;
2210            }
2211
2212            for (key, value) in pending_mark.attributes {
2213                self.mark_with_txn(
2214                    txn,
2215                    pending_mark.start,
2216                    pending_mark.end,
2217                    key.deref(),
2218                    value,
2219                    false,
2220                )?;
2221            }
2222        }
2223
2224        Ok(())
2225    }
2226
2227    pub fn update(&self, text: &str, options: UpdateOptions) -> Result<(), UpdateTimeoutError> {
2228        let old_str = self.to_string();
2229        let new = text.chars().map(|x| x as u32).collect::<Vec<u32>>();
2230        let old = old_str.chars().map(|x| x as u32).collect::<Vec<u32>>();
2231        diff(
2232            &mut OperateProxy::new(text_update::DiffHook::new(self, &new)),
2233            options,
2234            &old,
2235            &new,
2236        )?;
2237        Ok(())
2238    }
2239
2240    pub fn update_by_line(
2241        &self,
2242        text: &str,
2243        options: UpdateOptions,
2244    ) -> Result<(), UpdateTimeoutError> {
2245        let hook = text_update::DiffHookForLine::new(self, text);
2246        let old_lines = hook.get_old_arr().to_vec();
2247        let new_lines = hook.get_new_arr().to_vec();
2248        diff(
2249            &mut OperateProxy::new(hook),
2250            options,
2251            &old_lines,
2252            &new_lines,
2253        )
2254    }
2255
2256    #[allow(clippy::inherent_to_string)]
2257    pub fn to_string(&self) -> String {
2258        match &self.inner {
2259            MaybeDetached::Detached(t) => t.lock().unwrap().value.to_string(),
2260            MaybeDetached::Attached(a) => a.get_value().into_string().unwrap().unwrap(),
2261        }
2262    }
2263
2264    pub fn get_cursor(&self, event_index: usize, side: Side) -> Option<Cursor> {
2265        self.get_cursor_internal(event_index, side, true)
2266    }
2267
2268    /// Get the stable position representation for the target pos
2269    pub(crate) fn get_cursor_internal(
2270        &self,
2271        index: usize,
2272        side: Side,
2273        get_by_event_index: bool,
2274    ) -> Option<Cursor> {
2275        match &self.inner {
2276            MaybeDetached::Detached(_) => None,
2277            MaybeDetached::Attached(a) => {
2278                let (id, len, origin_pos) = a.with_state(|s| {
2279                    let s = s.as_richtext_state_mut().unwrap();
2280                    (
2281                        s.get_stable_position(index, get_by_event_index),
2282                        if get_by_event_index {
2283                            s.len_event()
2284                        } else {
2285                            s.len_unicode()
2286                        },
2287                        if get_by_event_index {
2288                            s.event_index_to_unicode_index(index)
2289                        } else {
2290                            index
2291                        },
2292                    )
2293                });
2294
2295                if len == 0 {
2296                    return Some(Cursor {
2297                        id: None,
2298                        container: self.id(),
2299                        side: if side == Side::Middle {
2300                            Side::Left
2301                        } else {
2302                            side
2303                        },
2304                        origin_pos: 0,
2305                    });
2306                }
2307
2308                if len <= index {
2309                    return Some(Cursor {
2310                        id: None,
2311                        container: self.id(),
2312                        side: Side::Right,
2313                        origin_pos: len,
2314                    });
2315                }
2316
2317                let id = id?;
2318                Some(Cursor {
2319                    id: Some(id),
2320                    container: self.id(),
2321                    side,
2322                    origin_pos,
2323                })
2324            }
2325        }
2326    }
2327
2328    pub(crate) fn convert_entity_index_to_event_index(&self, entity_index: usize) -> usize {
2329        match &self.inner {
2330            MaybeDetached::Detached(s) => s
2331                .lock()
2332                .unwrap()
2333                .value
2334                .entity_index_to_event_index(entity_index),
2335            MaybeDetached::Attached(a) => {
2336                let mut pos = 0;
2337                a.with_state(|s| {
2338                    let s = s.as_richtext_state_mut().unwrap();
2339                    pos = s.entity_index_to_event_index(entity_index);
2340                });
2341                pos
2342            }
2343        }
2344    }
2345
2346    fn get_delta(&self) -> Vec<TextDelta> {
2347        self.with_state(|state| {
2348            let state = state.as_richtext_state_mut().unwrap();
2349            Ok(state.get_delta())
2350        })
2351        .unwrap()
2352    }
2353
2354    pub fn is_deleted(&self) -> bool {
2355        match &self.inner {
2356            MaybeDetached::Detached(_) => false,
2357            MaybeDetached::Attached(a) => a.is_deleted(),
2358        }
2359    }
2360
2361    pub fn push_str(&self, s: &str) -> LoroResult<()> {
2362        self.insert_utf8(self.len_utf8(), s)
2363    }
2364
2365    pub fn clear(&self) -> LoroResult<()> {
2366        match &self.inner {
2367            MaybeDetached::Detached(mutex) => {
2368                let mut t = mutex.lock().unwrap();
2369                let len = t.value.len_unicode();
2370                let ranges = t.value.get_text_entity_ranges(0, len, PosType::Unicode)?;
2371                for range in ranges.iter().rev() {
2372                    t.value
2373                        .drain_by_entity_index(range.entity_start, range.entity_len(), None);
2374                }
2375                Ok(())
2376            }
2377            MaybeDetached::Attached(a) => a.with_txn(|txn| {
2378                let len = a.with_state(|s| s.as_richtext_state_mut().unwrap().len_unicode());
2379                self.delete_with_txn_inline(txn, 0, len, PosType::Unicode)
2380            }),
2381        }
2382    }
2383}
2384
2385fn event_len(s: &str) -> usize {
2386    if cfg!(feature = "wasm") {
2387        count_utf16_len(s.as_bytes())
2388    } else {
2389        s.chars().count()
2390    }
2391}
2392
2393impl ListHandler {
2394    /// Create a new container that is detached from the document.
2395    /// The edits on a detached container will not be persisted.
2396    /// To attach the container to the document, please insert it into an attached container.
2397    pub fn new_detached() -> Self {
2398        Self {
2399            inner: MaybeDetached::new_detached(Vec::new()),
2400        }
2401    }
2402
2403    pub fn insert(&self, pos: usize, v: impl Into<LoroValue>) -> LoroResult<()> {
2404        match &self.inner {
2405            MaybeDetached::Detached(l) => {
2406                let mut list = l.lock().unwrap();
2407                list.value.insert(pos, ValueOrHandler::Value(v.into()));
2408                Ok(())
2409            }
2410            MaybeDetached::Attached(a) => {
2411                a.with_txn(|txn| self.insert_with_txn(txn, pos, v.into()))
2412            }
2413        }
2414    }
2415
2416    pub fn insert_with_txn(
2417        &self,
2418        txn: &mut Transaction,
2419        pos: usize,
2420        v: LoroValue,
2421    ) -> LoroResult<()> {
2422        if pos > self.len() {
2423            return Err(LoroError::OutOfBound {
2424                pos,
2425                info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
2426                len: self.len(),
2427            });
2428        }
2429
2430        let inner = self.inner.try_attached_state()?;
2431        if let Some(_container) = v.as_container() {
2432            return Err(LoroError::ArgErr(
2433                INSERT_CONTAINER_VALUE_ARG_ERROR
2434                    .to_string()
2435                    .into_boxed_str(),
2436            ));
2437        }
2438
2439        txn.apply_local_op(
2440            inner.container_idx,
2441            crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Insert {
2442                slice: ListSlice::RawData(Cow::Owned(vec![v.clone()])),
2443                pos,
2444            }),
2445            EventHint::InsertList { len: 1, pos },
2446            &inner.doc,
2447        )
2448    }
2449
2450    pub fn push(&self, v: impl Into<LoroValue>) -> LoroResult<()> {
2451        match &self.inner {
2452            MaybeDetached::Detached(l) => {
2453                let mut list = l.lock().unwrap();
2454                list.value.push(ValueOrHandler::Value(v.into()));
2455                Ok(())
2456            }
2457            MaybeDetached::Attached(a) => a.with_txn(|txn| self.push_with_txn(txn, v.into())),
2458        }
2459    }
2460
2461    pub fn push_with_txn(&self, txn: &mut Transaction, v: LoroValue) -> LoroResult<()> {
2462        let pos = self.len();
2463        self.insert_with_txn(txn, pos, v)
2464    }
2465
2466    pub fn pop(&self) -> LoroResult<Option<LoroValue>> {
2467        match &self.inner {
2468            MaybeDetached::Detached(l) => {
2469                let mut list = l.lock().unwrap();
2470                Ok(list.value.pop().map(|v| v.to_value()))
2471            }
2472            MaybeDetached::Attached(a) => a.with_txn(|txn| self.pop_with_txn(txn)),
2473        }
2474    }
2475
2476    pub fn pop_with_txn(&self, txn: &mut Transaction) -> LoroResult<Option<LoroValue>> {
2477        let len = self.len();
2478        if len == 0 {
2479            return Ok(None);
2480        }
2481
2482        let v = self.get(len - 1);
2483        self.delete_with_txn(txn, len - 1, 1)?;
2484        Ok(v)
2485    }
2486
2487    pub fn insert_container<H: HandlerTrait>(&self, pos: usize, child: H) -> LoroResult<H> {
2488        match &self.inner {
2489            MaybeDetached::Detached(l) => {
2490                let mut list = l.lock().unwrap();
2491                list.value
2492                    .insert(pos, ValueOrHandler::Handler(child.to_handler()));
2493                Ok(child)
2494            }
2495            MaybeDetached::Attached(a) => {
2496                a.with_txn(|txn| self.insert_container_with_txn(txn, pos, child))
2497            }
2498        }
2499    }
2500
2501    pub fn push_container<H: HandlerTrait>(&self, child: H) -> LoroResult<H> {
2502        self.insert_container(self.len(), child)
2503    }
2504
2505    pub fn insert_container_with_txn<H: HandlerTrait>(
2506        &self,
2507        txn: &mut Transaction,
2508        pos: usize,
2509        child: H,
2510    ) -> LoroResult<H> {
2511        if pos > self.len() {
2512            return Err(LoroError::OutOfBound {
2513                pos,
2514                info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
2515                len: self.len(),
2516            });
2517        }
2518
2519        let inner = self.inner.try_attached_state()?;
2520        let id = txn.next_id();
2521        let container_id = ContainerID::new_normal(id, child.kind());
2522        let v = LoroValue::Container(container_id.clone());
2523        txn.apply_local_op(
2524            inner.container_idx,
2525            crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Insert {
2526                slice: ListSlice::RawData(Cow::Owned(vec![v.clone()])),
2527                pos,
2528            }),
2529            EventHint::InsertList { len: 1, pos },
2530            &inner.doc,
2531        )?;
2532        let ans = child.attach(txn, inner, container_id)?;
2533        Ok(ans)
2534    }
2535
2536    pub fn delete(&self, pos: usize, len: usize) -> LoroResult<()> {
2537        match &self.inner {
2538            MaybeDetached::Detached(l) => {
2539                let mut list = l.lock().unwrap();
2540                list.value.drain(pos..pos + len);
2541                Ok(())
2542            }
2543            MaybeDetached::Attached(a) => a.with_txn(|txn| self.delete_with_txn(txn, pos, len)),
2544        }
2545    }
2546
2547    pub fn delete_with_txn(&self, txn: &mut Transaction, pos: usize, len: usize) -> LoroResult<()> {
2548        if len == 0 {
2549            return Ok(());
2550        }
2551
2552        if pos + len > self.len() {
2553            return Err(LoroError::OutOfBound {
2554                pos: pos + len,
2555                info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
2556                len: self.len(),
2557            });
2558        }
2559
2560        let inner = self.inner.try_attached_state()?;
2561        let ids: Vec<_> = inner.with_state(|state| {
2562            let list = state.as_list_state().unwrap();
2563            (pos..pos + len)
2564                .map(|i| list.get_id_at(i).unwrap())
2565                .collect()
2566        });
2567
2568        for id in ids.into_iter() {
2569            txn.apply_local_op(
2570                inner.container_idx,
2571                crate::op::RawOpContent::List(ListOp::Delete(DeleteSpanWithId::new(
2572                    id.id(),
2573                    pos as isize,
2574                    1,
2575                ))),
2576                EventHint::DeleteList(DeleteSpan::new(pos as isize, 1)),
2577                &inner.doc,
2578            )?;
2579        }
2580
2581        Ok(())
2582    }
2583
2584    pub fn get_child_handler(&self, index: usize) -> LoroResult<Handler> {
2585        match &self.inner {
2586            MaybeDetached::Detached(l) => {
2587                let list = l.lock().unwrap();
2588                let value = list.value.get(index).ok_or(LoroError::OutOfBound {
2589                    pos: index,
2590                    info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
2591                    len: list.value.len(),
2592                })?;
2593                match value {
2594                    ValueOrHandler::Handler(h) => Ok(h.clone()),
2595                    _ => Err(LoroError::ArgErr(
2596                        format!(
2597                            "Expected container at index {}, but found {:?}",
2598                            index, value
2599                        )
2600                        .into_boxed_str(),
2601                    )),
2602                }
2603            }
2604            MaybeDetached::Attached(a) => {
2605                let Some(value) = a.with_state(|state| {
2606                    state.as_list_state().as_ref().unwrap().get(index).cloned()
2607                }) else {
2608                    return Err(LoroError::OutOfBound {
2609                        pos: index,
2610                        info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
2611                        len: a.with_state(|state| state.as_list_state().unwrap().len()),
2612                    });
2613                };
2614                match value {
2615                    LoroValue::Container(id) => Ok(create_handler(a, id)),
2616                    _ => Err(LoroError::ArgErr(
2617                        format!(
2618                            "Expected container at index {}, but found {:?}",
2619                            index, value
2620                        )
2621                        .into_boxed_str(),
2622                    )),
2623                }
2624            }
2625        }
2626    }
2627
2628    pub fn len(&self) -> usize {
2629        match &self.inner {
2630            MaybeDetached::Detached(l) => l.lock().unwrap().value.len(),
2631            MaybeDetached::Attached(a) => {
2632                a.with_state(|state| state.as_list_state().unwrap().len())
2633            }
2634        }
2635    }
2636
2637    pub fn is_empty(&self) -> bool {
2638        self.len() == 0
2639    }
2640
2641    pub fn get_deep_value_with_id(&self) -> LoroResult<LoroValue> {
2642        let inner = self.inner.try_attached_state()?;
2643        Ok(inner.with_doc_state(|state| {
2644            state.get_container_deep_value_with_id(inner.container_idx, None)
2645        }))
2646    }
2647
2648    pub fn get(&self, index: usize) -> Option<LoroValue> {
2649        match &self.inner {
2650            MaybeDetached::Detached(l) => l.lock().unwrap().value.get(index).map(|x| x.to_value()),
2651            MaybeDetached::Attached(a) => a.with_state(|state| {
2652                let a = state.as_list_state().unwrap();
2653                a.get(index).cloned()
2654            }),
2655        }
2656    }
2657
2658    /// Get value at given index, if it's a container, return a handler to the container
2659    pub fn get_(&self, index: usize) -> Option<ValueOrHandler> {
2660        match &self.inner {
2661            MaybeDetached::Detached(l) => {
2662                let l = l.lock().unwrap();
2663                l.value.get(index).cloned()
2664            }
2665            MaybeDetached::Attached(inner) => {
2666                let value =
2667                    inner.with_state(|state| state.as_list_state().unwrap().get(index).cloned());
2668                match value {
2669                    Some(LoroValue::Container(container_id)) => Some(ValueOrHandler::Handler(
2670                        create_handler(inner, container_id.clone()),
2671                    )),
2672                    Some(value) => Some(ValueOrHandler::Value(value.clone())),
2673                    None => None,
2674                }
2675            }
2676        }
2677    }
2678
2679    pub fn for_each<I>(&self, mut f: I)
2680    where
2681        I: FnMut(ValueOrHandler),
2682    {
2683        match &self.inner {
2684            MaybeDetached::Detached(l) => {
2685                let l = l.lock().unwrap();
2686                for v in l.value.iter() {
2687                    f(v.clone())
2688                }
2689            }
2690            MaybeDetached::Attached(inner) => {
2691                let mut temp = vec![];
2692                inner.with_state(|state| {
2693                    let a = state.as_list_state().unwrap();
2694                    for v in a.iter() {
2695                        match v {
2696                            LoroValue::Container(c) => {
2697                                temp.push(ValueOrHandler::Handler(create_handler(
2698                                    inner,
2699                                    c.clone(),
2700                                )));
2701                            }
2702                            value => {
2703                                temp.push(ValueOrHandler::Value(value.clone()));
2704                            }
2705                        }
2706                    }
2707                });
2708                for v in temp.into_iter() {
2709                    f(v);
2710                }
2711            }
2712        }
2713    }
2714
2715    pub fn get_cursor(&self, pos: usize, side: Side) -> Option<Cursor> {
2716        match &self.inner {
2717            MaybeDetached::Detached(_) => None,
2718            MaybeDetached::Attached(a) => {
2719                let (id, len) = a.with_state(|s| {
2720                    let l = s.as_list_state().unwrap();
2721                    (l.get_id_at(pos), l.len())
2722                });
2723
2724                if len == 0 {
2725                    return Some(Cursor {
2726                        id: None,
2727                        container: self.id(),
2728                        side: if side == Side::Middle {
2729                            Side::Left
2730                        } else {
2731                            side
2732                        },
2733                        origin_pos: 0,
2734                    });
2735                }
2736
2737                if len <= pos {
2738                    return Some(Cursor {
2739                        id: None,
2740                        container: self.id(),
2741                        side: Side::Right,
2742                        origin_pos: len,
2743                    });
2744                }
2745
2746                let id = id?;
2747                Some(Cursor {
2748                    id: Some(id.id()),
2749                    container: self.id(),
2750                    side,
2751                    origin_pos: pos,
2752                })
2753            }
2754        }
2755    }
2756
2757    fn apply_delta(
2758        &self,
2759        delta: loro_delta::DeltaRope<
2760            loro_delta::array_vec::ArrayVec<ValueOrHandler, 8>,
2761            crate::event::ListDeltaMeta,
2762        >,
2763        on_container_remap: &mut dyn FnMut(ContainerID, ContainerID),
2764    ) -> LoroResult<()> {
2765        match &self.inner {
2766            MaybeDetached::Detached(_) => unimplemented!(),
2767            MaybeDetached::Attached(_) => {
2768                let mut index = 0;
2769                for item in delta.iter() {
2770                    match item {
2771                        loro_delta::DeltaItem::Retain { len, .. } => {
2772                            index += len;
2773                        }
2774                        loro_delta::DeltaItem::Replace { value, delete, .. } => {
2775                            if *delete > 0 {
2776                                self.delete(index, *delete)?;
2777                            }
2778
2779                            for v in value.iter() {
2780                                match v {
2781                                    ValueOrHandler::Value(LoroValue::Container(old_id)) => {
2782                                        let new_h = self.insert_container(
2783                                            index,
2784                                            Handler::new_unattached(old_id.container_type()),
2785                                        )?;
2786                                        let new_id = new_h.id();
2787                                        on_container_remap(old_id.clone(), new_id);
2788                                    }
2789                                    ValueOrHandler::Handler(h) => {
2790                                        let old_id = h.id();
2791                                        let new_h = self.insert_container(
2792                                            index,
2793                                            Handler::new_unattached(old_id.container_type()),
2794                                        )?;
2795                                        let new_id = new_h.id();
2796                                        on_container_remap(old_id, new_id);
2797                                    }
2798                                    ValueOrHandler::Value(v) => {
2799                                        self.insert(index, v.clone())?;
2800                                    }
2801                                }
2802
2803                                index += 1;
2804                            }
2805                        }
2806                    }
2807                }
2808            }
2809        }
2810
2811        Ok(())
2812    }
2813
2814    pub fn is_deleted(&self) -> bool {
2815        match &self.inner {
2816            MaybeDetached::Detached(_) => false,
2817            MaybeDetached::Attached(a) => a.is_deleted(),
2818        }
2819    }
2820
2821    pub fn clear(&self) -> LoroResult<()> {
2822        match &self.inner {
2823            MaybeDetached::Detached(l) => {
2824                let mut l = l.lock().unwrap();
2825                l.value.clear();
2826                Ok(())
2827            }
2828            MaybeDetached::Attached(a) => a.with_txn(|txn| self.clear_with_txn(txn)),
2829        }
2830    }
2831
2832    pub fn clear_with_txn(&self, txn: &mut Transaction) -> LoroResult<()> {
2833        self.delete_with_txn(txn, 0, self.len())
2834    }
2835
2836    pub fn get_id_at(&self, pos: usize) -> Option<ID> {
2837        match &self.inner {
2838            MaybeDetached::Detached(_) => None,
2839            MaybeDetached::Attached(a) => a.with_state(|state| {
2840                state
2841                    .as_list_state()
2842                    .unwrap()
2843                    .get_id_at(pos)
2844                    .map(|x| x.id())
2845            }),
2846        }
2847    }
2848}
2849
2850impl MovableListHandler {
2851    pub fn insert(&self, pos: usize, v: impl Into<LoroValue>) -> LoroResult<()> {
2852        match &self.inner {
2853            MaybeDetached::Detached(d) => {
2854                let mut d = d.lock().unwrap();
2855                if pos > d.value.len() {
2856                    return Err(LoroError::OutOfBound {
2857                        pos,
2858                        info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
2859                        len: d.value.len(),
2860                    });
2861                }
2862                d.value.insert(pos, ValueOrHandler::Value(v.into()));
2863                Ok(())
2864            }
2865            MaybeDetached::Attached(a) => {
2866                a.with_txn(|txn| self.insert_with_txn(txn, pos, v.into()))
2867            }
2868        }
2869    }
2870
2871    #[instrument(skip_all)]
2872    pub fn insert_with_txn(
2873        &self,
2874        txn: &mut Transaction,
2875        pos: usize,
2876        v: LoroValue,
2877    ) -> LoroResult<()> {
2878        if pos > self.len() {
2879            return Err(LoroError::OutOfBound {
2880                pos,
2881                info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
2882                len: self.len(),
2883            });
2884        }
2885
2886        if v.is_container() {
2887            return Err(LoroError::ArgErr(
2888                INSERT_CONTAINER_VALUE_ARG_ERROR
2889                    .to_string()
2890                    .into_boxed_str(),
2891            ));
2892        }
2893
2894        let op_index = self.with_state(|state| {
2895            let list = state.as_movable_list_state().unwrap();
2896            Ok(list
2897                .convert_index(pos, IndexType::ForUser, IndexType::ForOp)
2898                .unwrap())
2899        })?;
2900
2901        let inner = self.inner.try_attached_state()?;
2902        txn.apply_local_op(
2903            inner.container_idx,
2904            crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Insert {
2905                slice: ListSlice::RawData(Cow::Owned(vec![v.clone()])),
2906                pos: op_index,
2907            }),
2908            EventHint::InsertList { len: 1, pos },
2909            &inner.doc,
2910        )
2911    }
2912
2913    #[inline]
2914    pub fn mov(&self, from: usize, to: usize) -> LoroResult<()> {
2915        match &self.inner {
2916            MaybeDetached::Detached(d) => {
2917                let mut d = d.lock().unwrap();
2918                if from >= d.value.len() {
2919                    return Err(LoroError::OutOfBound {
2920                        pos: from,
2921                        info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
2922                        len: d.value.len(),
2923                    });
2924                }
2925                if to >= d.value.len() {
2926                    return Err(LoroError::OutOfBound {
2927                        pos: to,
2928                        info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
2929                        len: d.value.len(),
2930                    });
2931                }
2932                let v = d.value.remove(from);
2933                d.value.insert(to, v);
2934                Ok(())
2935            }
2936            MaybeDetached::Attached(a) => a.with_txn(|txn| self.move_with_txn(txn, from, to)),
2937        }
2938    }
2939
2940    /// Move element from `from` to `to`. After this op, elem will be at pos `to`.
2941    #[instrument(skip_all)]
2942    pub fn move_with_txn(&self, txn: &mut Transaction, from: usize, to: usize) -> LoroResult<()> {
2943        if from == to {
2944            return Ok(());
2945        }
2946
2947        if from >= self.len() {
2948            return Err(LoroError::OutOfBound {
2949                pos: from,
2950                info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
2951                len: self.len(),
2952            });
2953        }
2954
2955        if to >= self.len() {
2956            return Err(LoroError::OutOfBound {
2957                pos: to,
2958                info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
2959                len: self.len(),
2960            });
2961        }
2962
2963        let (op_from, op_to, elem_id, value) = self.with_state(|state| {
2964            let list = state.as_movable_list_state().unwrap();
2965            let (elem_id, elem) = list
2966                .get_elem_at_given_pos(from, IndexType::ForUser)
2967                .unwrap();
2968            Ok((
2969                list.convert_index(from, IndexType::ForUser, IndexType::ForOp)
2970                    .unwrap(),
2971                list.convert_index(to, IndexType::ForUser, IndexType::ForOp)
2972                    .unwrap(),
2973                elem_id,
2974                elem.value().clone(),
2975            ))
2976        })?;
2977
2978        let inner = self.inner.try_attached_state()?;
2979        txn.apply_local_op(
2980            inner.container_idx,
2981            crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Move {
2982                from: op_from as u32,
2983                to: op_to as u32,
2984                elem_id: elem_id.to_id(),
2985            }),
2986            EventHint::Move {
2987                value,
2988                from: from as u32,
2989                to: to as u32,
2990            },
2991            &inner.doc,
2992        )
2993    }
2994
2995    pub fn push(&self, v: LoroValue) -> LoroResult<()> {
2996        match &self.inner {
2997            MaybeDetached::Detached(d) => {
2998                let mut d = d.lock().unwrap();
2999                d.value.push(v.into());
3000                Ok(())
3001            }
3002            MaybeDetached::Attached(a) => a.with_txn(|txn| self.push_with_txn(txn, v)),
3003        }
3004    }
3005
3006    pub fn push_with_txn(&self, txn: &mut Transaction, v: LoroValue) -> LoroResult<()> {
3007        let pos = self.len();
3008        self.insert_with_txn(txn, pos, v)
3009    }
3010
3011    pub fn pop_(&self) -> LoroResult<Option<ValueOrHandler>> {
3012        match &self.inner {
3013            MaybeDetached::Detached(d) => {
3014                let mut d = d.lock().unwrap();
3015                Ok(d.value.pop())
3016            }
3017            MaybeDetached::Attached(a) => {
3018                let last = self.len() - 1;
3019                let ans = self.get_(last);
3020                a.with_txn(|txn| self.pop_with_txn(txn))?;
3021                Ok(ans)
3022            }
3023        }
3024    }
3025
3026    pub fn pop(&self) -> LoroResult<Option<LoroValue>> {
3027        match &self.inner {
3028            MaybeDetached::Detached(a) => {
3029                let mut a = a.lock().unwrap();
3030                Ok(a.value.pop().map(|x| x.to_value()))
3031            }
3032            MaybeDetached::Attached(a) => a.with_txn(|txn| self.pop_with_txn(txn)),
3033        }
3034    }
3035
3036    pub fn pop_with_txn(&self, txn: &mut Transaction) -> LoroResult<Option<LoroValue>> {
3037        let len = self.len();
3038        if len == 0 {
3039            return Ok(None);
3040        }
3041
3042        let v = self.get(len - 1);
3043        self.delete_with_txn(txn, len - 1, 1)?;
3044        Ok(v)
3045    }
3046
3047    pub fn insert_container<H: HandlerTrait>(&self, pos: usize, child: H) -> LoroResult<H> {
3048        match &self.inner {
3049            MaybeDetached::Detached(d) => {
3050                let mut d = d.lock().unwrap();
3051                if pos > d.value.len() {
3052                    return Err(LoroError::OutOfBound {
3053                        pos,
3054                        info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
3055                        len: d.value.len(),
3056                    });
3057                }
3058                d.value
3059                    .insert(pos, ValueOrHandler::Handler(child.to_handler()));
3060                Ok(child)
3061            }
3062            MaybeDetached::Attached(a) => {
3063                a.with_txn(|txn| self.insert_container_with_txn(txn, pos, child))
3064            }
3065        }
3066    }
3067
3068    pub fn push_container<H: HandlerTrait>(&self, child: H) -> LoroResult<H> {
3069        self.insert_container(self.len(), child)
3070    }
3071
3072    pub fn insert_container_with_txn<H: HandlerTrait>(
3073        &self,
3074        txn: &mut Transaction,
3075        pos: usize,
3076        child: H,
3077    ) -> LoroResult<H> {
3078        if pos > self.len() {
3079            return Err(LoroError::OutOfBound {
3080                pos,
3081                info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
3082                len: self.len(),
3083            });
3084        }
3085
3086        let op_index = self.with_state(|state| {
3087            let list = state.as_movable_list_state().unwrap();
3088            Ok(list
3089                .convert_index(pos, IndexType::ForUser, IndexType::ForOp)
3090                .unwrap())
3091        })?;
3092
3093        let id = txn.next_id();
3094        let container_id = ContainerID::new_normal(id, child.kind());
3095        let v = LoroValue::Container(container_id.clone());
3096        let inner = self.inner.try_attached_state()?;
3097        txn.apply_local_op(
3098            inner.container_idx,
3099            crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Insert {
3100                slice: ListSlice::RawData(Cow::Owned(vec![v.clone()])),
3101                pos: op_index,
3102            }),
3103            EventHint::InsertList { len: 1, pos },
3104            &inner.doc,
3105        )?;
3106        child.attach(txn, inner, container_id)
3107    }
3108
3109    pub fn set(&self, index: usize, value: impl Into<LoroValue>) -> LoroResult<()> {
3110        match &self.inner {
3111            MaybeDetached::Detached(d) => {
3112                let mut d = d.lock().unwrap();
3113                if index >= d.value.len() {
3114                    return Err(LoroError::OutOfBound {
3115                        pos: index,
3116                        info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
3117                        len: d.value.len(),
3118                    });
3119                }
3120                d.value[index] = ValueOrHandler::Value(value.into());
3121                Ok(())
3122            }
3123            MaybeDetached::Attached(a) => {
3124                a.with_txn(|txn| self.set_with_txn(txn, index, value.into()))
3125            }
3126        }
3127    }
3128
3129    pub fn set_with_txn(
3130        &self,
3131        txn: &mut Transaction,
3132        index: usize,
3133        value: LoroValue,
3134    ) -> LoroResult<()> {
3135        if index >= self.len() {
3136            return Err(LoroError::OutOfBound {
3137                pos: index,
3138                info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
3139                len: self.len(),
3140            });
3141        }
3142
3143        let inner = self.inner.try_attached_state()?;
3144        let Some(elem_id) = self.with_state(|state| {
3145            let list = state.as_movable_list_state().unwrap();
3146            Ok(list.get_elem_id_at(index, IndexType::ForUser))
3147        })?
3148        else {
3149            unreachable!()
3150        };
3151
3152        let op = crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Set {
3153            elem_id: elem_id.to_id(),
3154            value: value.clone(),
3155        });
3156
3157        let hint = EventHint::SetList { index, value };
3158        txn.apply_local_op(inner.container_idx, op, hint, &inner.doc)
3159    }
3160
3161    pub fn set_container<H: HandlerTrait>(&self, pos: usize, child: H) -> LoroResult<H> {
3162        match &self.inner {
3163            MaybeDetached::Detached(d) => {
3164                let mut d = d.lock().unwrap();
3165                d.value[pos] = ValueOrHandler::Handler(child.to_handler());
3166                Ok(child)
3167            }
3168            MaybeDetached::Attached(a) => {
3169                a.with_txn(|txn| self.set_container_with_txn(txn, pos, child))
3170            }
3171        }
3172    }
3173
3174    pub fn set_container_with_txn<H: HandlerTrait>(
3175        &self,
3176        txn: &mut Transaction,
3177        pos: usize,
3178        child: H,
3179    ) -> LoroResult<H> {
3180        let id = txn.next_id();
3181        let container_id = ContainerID::new_normal(id, child.kind());
3182        let v = LoroValue::Container(container_id.clone());
3183        let Some(elem_id) = self.with_state(|state| {
3184            let list = state.as_movable_list_state().unwrap();
3185            Ok(list.get_elem_id_at(pos, IndexType::ForUser))
3186        })?
3187        else {
3188            let len = self.len();
3189            if pos >= len {
3190                return Err(LoroError::OutOfBound {
3191                    pos,
3192                    len,
3193                    info: "".into(),
3194                });
3195            } else {
3196                unreachable!()
3197            }
3198        };
3199        let inner = self.inner.try_attached_state()?;
3200        txn.apply_local_op(
3201            inner.container_idx,
3202            crate::op::RawOpContent::List(crate::container::list::list_op::ListOp::Set {
3203                elem_id: elem_id.to_id(),
3204                value: v.clone(),
3205            }),
3206            EventHint::SetList {
3207                index: pos,
3208                value: v,
3209            },
3210            &inner.doc,
3211        )?;
3212
3213        child.attach(txn, inner, container_id)
3214    }
3215
3216    pub fn delete(&self, pos: usize, len: usize) -> LoroResult<()> {
3217        match &self.inner {
3218            MaybeDetached::Detached(d) => {
3219                let mut d = d.lock().unwrap();
3220                d.value.drain(pos..pos + len);
3221                Ok(())
3222            }
3223            MaybeDetached::Attached(a) => a.with_txn(|txn| self.delete_with_txn(txn, pos, len)),
3224        }
3225    }
3226
3227    #[instrument(skip_all)]
3228    pub fn delete_with_txn(&self, txn: &mut Transaction, pos: usize, len: usize) -> LoroResult<()> {
3229        if len == 0 {
3230            return Ok(());
3231        }
3232
3233        if pos + len > self.len() {
3234            return Err(LoroError::OutOfBound {
3235                pos: pos + len,
3236                info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
3237                len: self.len(),
3238            });
3239        }
3240
3241        let (ids, new_poses) = self.with_state(|state| {
3242            let list = state.as_movable_list_state().unwrap();
3243            let ids: Vec<_> = (pos..pos + len)
3244                .map(|i| list.get_list_id_at(i, IndexType::ForUser).unwrap())
3245                .collect();
3246            let poses: Vec<_> = (pos..pos + len)
3247                // need to -i because we delete the previous ones
3248                .map(|user_index| {
3249                    let op_index = list
3250                        .convert_index(user_index, IndexType::ForUser, IndexType::ForOp)
3251                        .unwrap();
3252                    assert!(op_index >= user_index);
3253                    op_index - (user_index - pos)
3254                })
3255                .collect();
3256            Ok((ids, poses))
3257        })?;
3258
3259        loro_common::info!(?pos, ?len, ?ids, ?new_poses, "delete_with_txn");
3260        let user_pos = pos;
3261        let inner = self.inner.try_attached_state()?;
3262        for (id, op_pos) in ids.into_iter().zip(new_poses.into_iter()) {
3263            txn.apply_local_op(
3264                inner.container_idx,
3265                crate::op::RawOpContent::List(ListOp::Delete(DeleteSpanWithId::new(
3266                    id,
3267                    op_pos as isize,
3268                    1,
3269                ))),
3270                EventHint::DeleteList(DeleteSpan::new(user_pos as isize, 1)),
3271                &inner.doc,
3272            )?;
3273        }
3274
3275        Ok(())
3276    }
3277
3278    pub fn get_child_handler(&self, index: usize) -> LoroResult<Handler> {
3279        match &self.inner {
3280            MaybeDetached::Detached(l) => {
3281                let list = l.lock().unwrap();
3282                let value = list.value.get(index).ok_or(LoroError::OutOfBound {
3283                    pos: index,
3284                    info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
3285                    len: list.value.len(),
3286                })?;
3287                match value {
3288                    ValueOrHandler::Handler(h) => Ok(h.clone()),
3289                    _ => Err(LoroError::ArgErr(
3290                        format!(
3291                            "Expected container at index {}, but found {:?}",
3292                            index, value
3293                        )
3294                        .into_boxed_str(),
3295                    )),
3296                }
3297            }
3298            MaybeDetached::Attached(a) => {
3299                let Some(value) = a.with_state(|state| {
3300                    state
3301                        .as_movable_list_state()
3302                        .as_ref()
3303                        .unwrap()
3304                        .get(index, IndexType::ForUser)
3305                        .cloned()
3306                }) else {
3307                    return Err(LoroError::OutOfBound {
3308                        pos: index,
3309                        info: format!("Position: {}:{}", file!(), line!()).into_boxed_str(),
3310                        len: a.with_state(|state| state.as_list_state().unwrap().len()),
3311                    });
3312                };
3313                match value {
3314                    LoroValue::Container(id) => Ok(create_handler(a, id)),
3315                    _ => Err(LoroError::ArgErr(
3316                        format!(
3317                            "Expected container at index {}, but found {:?}",
3318                            index, value
3319                        )
3320                        .into_boxed_str(),
3321                    )),
3322                }
3323            }
3324        }
3325    }
3326
3327    pub fn len(&self) -> usize {
3328        match &self.inner {
3329            MaybeDetached::Detached(d) => {
3330                let d = d.lock().unwrap();
3331                d.value.len()
3332            }
3333            MaybeDetached::Attached(a) => {
3334                a.with_state(|state| state.as_movable_list_state().unwrap().len())
3335            }
3336        }
3337    }
3338
3339    pub fn is_empty(&self) -> bool {
3340        self.len() == 0
3341    }
3342
3343    pub fn get_deep_value_with_id(&self) -> LoroValue {
3344        let inner = self.inner.try_attached_state().unwrap();
3345        inner
3346            .doc
3347            .state
3348            .lock()
3349            .unwrap()
3350            .get_container_deep_value_with_id(inner.container_idx, None)
3351    }
3352
3353    pub fn get(&self, index: usize) -> Option<LoroValue> {
3354        match &self.inner {
3355            MaybeDetached::Detached(d) => {
3356                let d = d.lock().unwrap();
3357                d.value.get(index).map(|v| v.to_value())
3358            }
3359            MaybeDetached::Attached(a) => a.with_state(|state| {
3360                let a = state.as_movable_list_state().unwrap();
3361                a.get(index, IndexType::ForUser).cloned()
3362            }),
3363        }
3364    }
3365
3366    /// Get value at given index, if it's a container, return a handler to the container
3367    pub fn get_(&self, index: usize) -> Option<ValueOrHandler> {
3368        match &self.inner {
3369            MaybeDetached::Detached(d) => {
3370                let d = d.lock().unwrap();
3371                d.value.get(index).cloned()
3372            }
3373            MaybeDetached::Attached(m) => m.with_state(|state| {
3374                let a = state.as_movable_list_state().unwrap();
3375                match a.get(index, IndexType::ForUser) {
3376                    Some(v) => {
3377                        if let LoroValue::Container(c) = v {
3378                            Some(ValueOrHandler::Handler(create_handler(m, c.clone())))
3379                        } else {
3380                            Some(ValueOrHandler::Value(v.clone()))
3381                        }
3382                    }
3383                    None => None,
3384                }
3385            }),
3386        }
3387    }
3388
3389    pub fn for_each<I>(&self, mut f: I)
3390    where
3391        I: FnMut(ValueOrHandler),
3392    {
3393        match &self.inner {
3394            MaybeDetached::Detached(d) => {
3395                let d = d.lock().unwrap();
3396                for v in d.value.iter() {
3397                    f(v.clone());
3398                }
3399            }
3400            MaybeDetached::Attached(m) => {
3401                let mut temp = vec![];
3402                m.with_state(|state| {
3403                    let a = state.as_movable_list_state().unwrap();
3404                    for v in a.iter() {
3405                        match v {
3406                            LoroValue::Container(c) => {
3407                                temp.push(ValueOrHandler::Handler(create_handler(m, c.clone())));
3408                            }
3409                            value => {
3410                                temp.push(ValueOrHandler::Value(value.clone()));
3411                            }
3412                        }
3413                    }
3414                });
3415
3416                for v in temp.into_iter() {
3417                    f(v);
3418                }
3419            }
3420        }
3421    }
3422
3423    pub fn log_internal_state(&self) -> String {
3424        match &self.inner {
3425            MaybeDetached::Detached(d) => {
3426                let d = d.lock().unwrap();
3427                format!("{:#?}", &d.value)
3428            }
3429            MaybeDetached::Attached(a) => a.with_state(|state| {
3430                let a = state.as_movable_list_state().unwrap();
3431                format!("{a:#?}")
3432            }),
3433        }
3434    }
3435
3436    pub fn new_detached() -> MovableListHandler {
3437        MovableListHandler {
3438            inner: MaybeDetached::new_detached(Default::default()),
3439        }
3440    }
3441
3442    pub fn get_cursor(&self, pos: usize, side: Side) -> Option<Cursor> {
3443        match &self.inner {
3444            MaybeDetached::Detached(_) => None,
3445            MaybeDetached::Attached(inner) => {
3446                let (id, len) = inner.with_state(|s| {
3447                    let l = s.as_movable_list_state().unwrap();
3448                    (l.get_list_item_id_at(pos), l.len())
3449                });
3450
3451                if len == 0 {
3452                    return Some(Cursor {
3453                        id: None,
3454                        container: self.id(),
3455                        side: if side == Side::Middle {
3456                            Side::Left
3457                        } else {
3458                            side
3459                        },
3460                        origin_pos: 0,
3461                    });
3462                }
3463
3464                if len <= pos {
3465                    return Some(Cursor {
3466                        id: None,
3467                        container: self.id(),
3468                        side: Side::Right,
3469                        origin_pos: len,
3470                    });
3471                }
3472
3473                let id = id?;
3474                Some(Cursor {
3475                    id: Some(id.id()),
3476                    container: self.id(),
3477                    side,
3478                    origin_pos: pos,
3479                })
3480            }
3481        }
3482    }
3483
3484    pub(crate) fn op_pos_to_user_pos(&self, new_pos: usize) -> usize {
3485        match &self.inner {
3486            MaybeDetached::Detached(_) => new_pos,
3487            MaybeDetached::Attached(inner) => {
3488                let mut pos = new_pos;
3489                inner.with_state(|s| {
3490                    let l = s.as_movable_list_state().unwrap();
3491                    pos = l
3492                        .convert_index(new_pos, IndexType::ForOp, IndexType::ForUser)
3493                        .unwrap_or(l.len());
3494                });
3495                pos
3496            }
3497        }
3498    }
3499
3500    pub fn is_deleted(&self) -> bool {
3501        match &self.inner {
3502            MaybeDetached::Detached(_) => false,
3503            MaybeDetached::Attached(a) => a.is_deleted(),
3504        }
3505    }
3506
3507    pub fn clear(&self) -> LoroResult<()> {
3508        match &self.inner {
3509            MaybeDetached::Detached(d) => {
3510                let mut d = d.lock().unwrap();
3511                d.value.clear();
3512                Ok(())
3513            }
3514            MaybeDetached::Attached(a) => a.with_txn(|txn| self.clear_with_txn(txn)),
3515        }
3516    }
3517
3518    pub fn clear_with_txn(&self, txn: &mut Transaction) -> LoroResult<()> {
3519        self.delete_with_txn(txn, 0, self.len())
3520    }
3521
3522    pub fn get_creator_at(&self, pos: usize) -> Option<PeerID> {
3523        match &self.inner {
3524            MaybeDetached::Detached(_) => None,
3525            MaybeDetached::Attached(a) => {
3526                a.with_state(|state| state.as_movable_list_state().unwrap().get_creator_at(pos))
3527            }
3528        }
3529    }
3530
3531    pub fn get_last_mover_at(&self, pos: usize) -> Option<PeerID> {
3532        match &self.inner {
3533            MaybeDetached::Detached(_) => None,
3534            MaybeDetached::Attached(a) => a.with_state(|state| {
3535                state
3536                    .as_movable_list_state()
3537                    .unwrap()
3538                    .get_last_mover_at(pos)
3539            }),
3540        }
3541    }
3542
3543    pub fn get_last_editor_at(&self, pos: usize) -> Option<PeerID> {
3544        match &self.inner {
3545            MaybeDetached::Detached(_) => None,
3546            MaybeDetached::Attached(a) => a.with_state(|state| {
3547                state
3548                    .as_movable_list_state()
3549                    .unwrap()
3550                    .get_last_editor_at(pos)
3551            }),
3552        }
3553    }
3554}
3555
3556impl MapHandler {
3557    /// Create a new container that is detached from the document.
3558    /// The edits on a detached container will not be persisted.
3559    /// To attach the container to the document, please insert it into an attached container.
3560    pub fn new_detached() -> Self {
3561        Self {
3562            inner: MaybeDetached::new_detached(Default::default()),
3563        }
3564    }
3565
3566    pub fn insert(&self, key: &str, value: impl Into<LoroValue>) -> LoroResult<()> {
3567        match &self.inner {
3568            MaybeDetached::Detached(m) => {
3569                let mut m = m.lock().unwrap();
3570                m.value
3571                    .insert(key.into(), ValueOrHandler::Value(value.into()));
3572                Ok(())
3573            }
3574            MaybeDetached::Attached(a) => {
3575                a.with_txn(|txn| self.insert_with_txn(txn, key, value.into()))
3576            }
3577        }
3578    }
3579
3580    /// This method will insert the value even if the same value is already in the given entry.
3581    fn insert_without_skipping(&self, key: &str, value: impl Into<LoroValue>) -> LoroResult<()> {
3582        match &self.inner {
3583            MaybeDetached::Detached(m) => {
3584                let mut m = m.lock().unwrap();
3585                m.value
3586                    .insert(key.into(), ValueOrHandler::Value(value.into()));
3587                Ok(())
3588            }
3589            MaybeDetached::Attached(a) => a.with_txn(|txn| {
3590                let this = &self;
3591                let value = value.into();
3592                if let Some(_value) = value.as_container() {
3593                    return Err(LoroError::ArgErr(
3594                        INSERT_CONTAINER_VALUE_ARG_ERROR
3595                            .to_string()
3596                            .into_boxed_str(),
3597                    ));
3598                }
3599
3600                let inner = this.inner.try_attached_state()?;
3601                txn.apply_local_op(
3602                    inner.container_idx,
3603                    crate::op::RawOpContent::Map(crate::container::map::MapSet {
3604                        key: key.into(),
3605                        value: Some(value.clone()),
3606                    }),
3607                    EventHint::Map {
3608                        key: key.into(),
3609                        value: Some(value.clone()),
3610                    },
3611                    &inner.doc,
3612                )
3613            }),
3614        }
3615    }
3616
3617    pub fn insert_with_txn(
3618        &self,
3619        txn: &mut Transaction,
3620        key: &str,
3621        value: LoroValue,
3622    ) -> LoroResult<()> {
3623        if let Some(_value) = value.as_container() {
3624            return Err(LoroError::ArgErr(
3625                INSERT_CONTAINER_VALUE_ARG_ERROR
3626                    .to_string()
3627                    .into_boxed_str(),
3628            ));
3629        }
3630
3631        if self.get(key).map(|x| x == value).unwrap_or(false) {
3632            // skip if the value is already set
3633            return Ok(());
3634        }
3635
3636        let inner = self.inner.try_attached_state()?;
3637        txn.apply_local_op(
3638            inner.container_idx,
3639            crate::op::RawOpContent::Map(crate::container::map::MapSet {
3640                key: key.into(),
3641                value: Some(value.clone()),
3642            }),
3643            EventHint::Map {
3644                key: key.into(),
3645                value: Some(value.clone()),
3646            },
3647            &inner.doc,
3648        )
3649    }
3650
3651    pub fn insert_container<T: HandlerTrait>(&self, key: &str, handler: T) -> LoroResult<T> {
3652        match &self.inner {
3653            MaybeDetached::Detached(m) => {
3654                let mut m = m.lock().unwrap();
3655                let to_insert = handler.to_handler();
3656                m.value
3657                    .insert(key.into(), ValueOrHandler::Handler(to_insert.clone()));
3658                Ok(handler)
3659            }
3660            MaybeDetached::Attached(a) => {
3661                a.with_txn(|txn| self.insert_container_with_txn(txn, key, handler))
3662            }
3663        }
3664    }
3665
3666    pub fn insert_container_with_txn<H: HandlerTrait>(
3667        &self,
3668        txn: &mut Transaction,
3669        key: &str,
3670        child: H,
3671    ) -> LoroResult<H> {
3672        let inner = self.inner.try_attached_state()?;
3673        let id = txn.next_id();
3674        let container_id = ContainerID::new_normal(id, child.kind());
3675        txn.apply_local_op(
3676            inner.container_idx,
3677            crate::op::RawOpContent::Map(crate::container::map::MapSet {
3678                key: key.into(),
3679                value: Some(LoroValue::Container(container_id.clone())),
3680            }),
3681            EventHint::Map {
3682                key: key.into(),
3683                value: Some(LoroValue::Container(container_id.clone())),
3684            },
3685            &inner.doc,
3686        )?;
3687
3688        child.attach(txn, inner, container_id)
3689    }
3690
3691    pub fn delete(&self, key: &str) -> LoroResult<()> {
3692        match &self.inner {
3693            MaybeDetached::Detached(m) => {
3694                let mut m = m.lock().unwrap();
3695                m.value.remove(key);
3696                Ok(())
3697            }
3698            MaybeDetached::Attached(a) => a.with_txn(|txn| self.delete_with_txn(txn, key)),
3699        }
3700    }
3701
3702    pub fn delete_with_txn(&self, txn: &mut Transaction, key: &str) -> LoroResult<()> {
3703        let inner = self.inner.try_attached_state()?;
3704        txn.apply_local_op(
3705            inner.container_idx,
3706            crate::op::RawOpContent::Map(crate::container::map::MapSet {
3707                key: key.into(),
3708                value: None,
3709            }),
3710            EventHint::Map {
3711                key: key.into(),
3712                value: None,
3713            },
3714            &inner.doc,
3715        )
3716    }
3717
3718    pub fn for_each<I>(&self, mut f: I)
3719    where
3720        I: FnMut(&str, ValueOrHandler),
3721    {
3722        match &self.inner {
3723            MaybeDetached::Detached(m) => {
3724                let m = m.lock().unwrap();
3725                for (k, v) in m.value.iter() {
3726                    f(k, v.clone());
3727                }
3728            }
3729            MaybeDetached::Attached(inner) => {
3730                let mut temp = vec![];
3731                inner.with_state(|state| {
3732                    let a = state.as_map_state().unwrap();
3733                    for (k, v) in a.iter() {
3734                        if let Some(v) = &v.value {
3735                            match v {
3736                                LoroValue::Container(c) => {
3737                                    temp.push((
3738                                        k.to_string(),
3739                                        ValueOrHandler::Handler(create_handler(inner, c.clone())),
3740                                    ));
3741                                }
3742                                value => {
3743                                    temp.push((k.to_string(), ValueOrHandler::Value(value.clone())))
3744                                }
3745                            }
3746                        }
3747                    }
3748                });
3749
3750                for (k, v) in temp.into_iter() {
3751                    f(&k, v.clone());
3752                }
3753            }
3754        }
3755    }
3756
3757    pub fn get_child_handler(&self, key: &str) -> LoroResult<Handler> {
3758        match &self.inner {
3759            MaybeDetached::Detached(m) => {
3760                let m = m.lock().unwrap();
3761                let value = m.value.get(key).unwrap();
3762                match value {
3763                    ValueOrHandler::Value(v) => Err(LoroError::ArgErr(
3764                        format!("Expected Handler but found {:?}", v).into_boxed_str(),
3765                    )),
3766                    ValueOrHandler::Handler(h) => Ok(h.clone()),
3767                }
3768            }
3769            MaybeDetached::Attached(inner) => {
3770                let container_id = inner.with_state(|state| {
3771                    state
3772                        .as_map_state()
3773                        .as_ref()
3774                        .unwrap()
3775                        .get(key)
3776                        .unwrap()
3777                        .as_container()
3778                        .unwrap()
3779                        .clone()
3780                });
3781                Ok(create_handler(inner, container_id))
3782            }
3783        }
3784    }
3785
3786    pub fn get_deep_value_with_id(&self) -> LoroResult<LoroValue> {
3787        match &self.inner {
3788            MaybeDetached::Detached(_) => Err(LoroError::MisuseDetachedContainer {
3789                method: "get_deep_value_with_id",
3790            }),
3791            MaybeDetached::Attached(inner) => Ok(inner.with_doc_state(|state| {
3792                state.get_container_deep_value_with_id(inner.container_idx, None)
3793            })),
3794        }
3795    }
3796
3797    pub fn get(&self, key: &str) -> Option<LoroValue> {
3798        match &self.inner {
3799            MaybeDetached::Detached(m) => {
3800                let m = m.lock().unwrap();
3801                m.value.get(key).map(|v| v.to_value())
3802            }
3803            MaybeDetached::Attached(inner) => {
3804                inner.with_state(|state| state.as_map_state().unwrap().get(key).cloned())
3805            }
3806        }
3807    }
3808
3809    /// Get the value at given key, if value is a container, return a handler to the container
3810    pub fn get_(&self, key: &str) -> Option<ValueOrHandler> {
3811        match &self.inner {
3812            MaybeDetached::Detached(m) => {
3813                let m = m.lock().unwrap();
3814                m.value.get(key).cloned()
3815            }
3816            MaybeDetached::Attached(inner) => {
3817                let value =
3818                    inner.with_state(|state| state.as_map_state().unwrap().get(key).cloned());
3819                match value {
3820                    Some(LoroValue::Container(container_id)) => Some(ValueOrHandler::Handler(
3821                        create_handler(inner, container_id.clone()),
3822                    )),
3823                    Some(value) => Some(ValueOrHandler::Value(value.clone())),
3824                    None => None,
3825                }
3826            }
3827        }
3828    }
3829
3830    pub fn get_or_create_container<C: HandlerTrait>(&self, key: &str, child: C) -> LoroResult<C> {
3831        if let Some(ans) = self.get_(key) {
3832            if let ValueOrHandler::Handler(h) = ans {
3833                let kind = h.kind();
3834                return C::from_handler(h).ok_or_else(move || {
3835                    LoroError::ArgErr(
3836                        format!("Expected value type {} but found {:?}", child.kind(), kind)
3837                            .into_boxed_str(),
3838                    )
3839                });
3840            } else if let ValueOrHandler::Value(LoroValue::Null) = ans {
3841                // do nothing
3842            } else {
3843                return Err(LoroError::ArgErr(
3844                    format!("Expected value type {} but found {:?}", child.kind(), ans)
3845                        .into_boxed_str(),
3846                ));
3847            }
3848        }
3849
3850        self.insert_container(key, child)
3851    }
3852
3853    pub fn contains_key(&self, key: &str) -> bool {
3854        self.get(key).is_some()
3855    }
3856
3857    pub fn len(&self) -> usize {
3858        match &self.inner {
3859            MaybeDetached::Detached(m) => m.lock().unwrap().value.len(),
3860            MaybeDetached::Attached(a) => a.with_state(|state| state.as_map_state().unwrap().len()),
3861        }
3862    }
3863
3864    pub fn is_empty(&self) -> bool {
3865        self.len() == 0
3866    }
3867
3868    pub fn is_deleted(&self) -> bool {
3869        match &self.inner {
3870            MaybeDetached::Detached(_) => false,
3871            MaybeDetached::Attached(a) => a.is_deleted(),
3872        }
3873    }
3874
3875    pub fn clear(&self) -> LoroResult<()> {
3876        match &self.inner {
3877            MaybeDetached::Detached(m) => {
3878                let mut m = m.lock().unwrap();
3879                m.value.clear();
3880                Ok(())
3881            }
3882            MaybeDetached::Attached(a) => a.with_txn(|txn| self.clear_with_txn(txn)),
3883        }
3884    }
3885
3886    pub fn clear_with_txn(&self, txn: &mut Transaction) -> LoroResult<()> {
3887        let keys: Vec<InternalString> = self.inner.try_attached_state()?.with_state(|state| {
3888            state
3889                .as_map_state()
3890                .unwrap()
3891                .iter()
3892                .map(|(k, _)| k.clone())
3893                .collect()
3894        });
3895
3896        for key in keys {
3897            self.delete_with_txn(txn, &key)?;
3898        }
3899
3900        Ok(())
3901    }
3902
3903    pub fn keys(&self) -> impl Iterator<Item = InternalString> + '_ {
3904        let mut keys: Vec<InternalString> = Vec::with_capacity(self.len());
3905        match &self.inner {
3906            MaybeDetached::Detached(m) => {
3907                let m = m.lock().unwrap();
3908                keys = m.value.keys().map(|x| x.as_str().into()).collect();
3909            }
3910            MaybeDetached::Attached(a) => {
3911                a.with_state(|state| {
3912                    for (k, v) in state.as_map_state().unwrap().iter() {
3913                        if v.value.is_some() {
3914                            keys.push(k.clone());
3915                        }
3916                    }
3917                });
3918            }
3919        }
3920
3921        keys.into_iter()
3922    }
3923
3924    pub fn values(&self) -> impl Iterator<Item = ValueOrHandler> + '_ {
3925        let mut values: Vec<ValueOrHandler> = Vec::with_capacity(self.len());
3926        match &self.inner {
3927            MaybeDetached::Detached(m) => {
3928                let m = m.lock().unwrap();
3929                values = m.value.values().cloned().collect();
3930            }
3931            MaybeDetached::Attached(a) => {
3932                a.with_state(|state| {
3933                    for (_, v) in state.as_map_state().unwrap().iter() {
3934                        let value = match &v.value {
3935                            Some(LoroValue::Container(container_id)) => {
3936                                ValueOrHandler::Handler(create_handler(a, container_id.clone()))
3937                            }
3938                            Some(value) => ValueOrHandler::Value(value.clone()),
3939                            None => continue,
3940                        };
3941                        values.push(value);
3942                    }
3943                });
3944            }
3945        }
3946
3947        values.into_iter()
3948    }
3949
3950    pub fn get_last_editor(&self, key: &str) -> Option<PeerID> {
3951        match &self.inner {
3952            MaybeDetached::Detached(_) => None,
3953            MaybeDetached::Attached(a) => a.with_state(|state| {
3954                let m = state.as_map_state().unwrap();
3955                m.get_last_edit_peer(key)
3956            }),
3957        }
3958    }
3959}
3960
3961fn with_txn<R>(doc: &LoroDoc, f: impl FnOnce(&mut Transaction) -> LoroResult<R>) -> LoroResult<R> {
3962    let txn = &doc.txn;
3963    let mut txn = txn.lock().unwrap();
3964    loop {
3965        if let Some(txn) = &mut *txn {
3966            return f(txn);
3967        } else if cfg!(target_arch = "wasm32") || !doc.can_edit() {
3968            return Err(LoroError::AutoCommitNotStarted);
3969        } else {
3970            drop(txn);
3971            #[cfg(loom)]
3972            loom::thread::yield_now();
3973            doc.start_auto_commit();
3974            txn = doc.txn.lock().unwrap();
3975        }
3976    }
3977}
3978
3979#[cfg(feature = "counter")]
3980pub mod counter {
3981
3982    use loro_common::LoroResult;
3983
3984    use crate::{
3985        txn::{EventHint, Transaction},
3986        HandlerTrait,
3987    };
3988
3989    use super::{create_handler, Handler, MaybeDetached};
3990
3991    #[derive(Clone)]
3992    pub struct CounterHandler {
3993        pub(super) inner: MaybeDetached<f64>,
3994    }
3995
3996    impl CounterHandler {
3997        pub fn new_detached() -> Self {
3998            Self {
3999                inner: MaybeDetached::new_detached(0.),
4000            }
4001        }
4002
4003        pub fn increment(&self, n: f64) -> LoroResult<()> {
4004            match &self.inner {
4005                MaybeDetached::Detached(d) => {
4006                    let d = &mut d.lock().unwrap().value;
4007                    *d += n;
4008                    Ok(())
4009                }
4010                MaybeDetached::Attached(a) => a.with_txn(|txn| self.increment_with_txn(txn, n)),
4011            }
4012        }
4013
4014        pub fn decrement(&self, n: f64) -> LoroResult<()> {
4015            match &self.inner {
4016                MaybeDetached::Detached(d) => {
4017                    let d = &mut d.lock().unwrap().value;
4018                    *d -= n;
4019                    Ok(())
4020                }
4021                MaybeDetached::Attached(a) => a.with_txn(|txn| self.increment_with_txn(txn, -n)),
4022            }
4023        }
4024
4025        fn increment_with_txn(&self, txn: &mut Transaction, n: f64) -> LoroResult<()> {
4026            let inner = self.inner.try_attached_state()?;
4027            txn.apply_local_op(
4028                inner.container_idx,
4029                crate::op::RawOpContent::Counter(n),
4030                EventHint::Counter(n),
4031                &inner.doc,
4032            )
4033        }
4034
4035        pub fn is_deleted(&self) -> bool {
4036            match &self.inner {
4037                MaybeDetached::Detached(_) => false,
4038                MaybeDetached::Attached(a) => a.is_deleted(),
4039            }
4040        }
4041
4042        pub fn clear(&self) -> LoroResult<()> {
4043            self.decrement(self.get_value().into_double().unwrap())
4044        }
4045    }
4046
4047    impl std::fmt::Debug for CounterHandler {
4048        fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
4049            match &self.inner {
4050                MaybeDetached::Detached(_) => write!(f, "CounterHandler Detached"),
4051                MaybeDetached::Attached(a) => write!(f, "CounterHandler {}", a.id),
4052            }
4053        }
4054    }
4055
4056    impl HandlerTrait for CounterHandler {
4057        fn is_attached(&self) -> bool {
4058            matches!(&self.inner, MaybeDetached::Attached(..))
4059        }
4060
4061        fn attached_handler(&self) -> Option<&crate::BasicHandler> {
4062            self.inner.attached_handler()
4063        }
4064
4065        fn get_value(&self) -> loro_common::LoroValue {
4066            match &self.inner {
4067                MaybeDetached::Detached(t) => {
4068                    let t = t.lock().unwrap();
4069                    t.value.into()
4070                }
4071                MaybeDetached::Attached(a) => a.get_value(),
4072            }
4073        }
4074
4075        fn get_deep_value(&self) -> loro_common::LoroValue {
4076            self.get_value()
4077        }
4078
4079        fn kind(&self) -> loro_common::ContainerType {
4080            loro_common::ContainerType::Counter
4081        }
4082
4083        fn to_handler(&self) -> super::Handler {
4084            Handler::Counter(self.clone())
4085        }
4086
4087        fn from_handler(h: super::Handler) -> Option<Self> {
4088            match h {
4089                Handler::Counter(x) => Some(x),
4090                _ => None,
4091            }
4092        }
4093
4094        fn attach(
4095            &self,
4096            txn: &mut crate::txn::Transaction,
4097            parent: &crate::BasicHandler,
4098            self_id: loro_common::ContainerID,
4099        ) -> loro_common::LoroResult<Self> {
4100            match &self.inner {
4101                MaybeDetached::Detached(v) => {
4102                    let mut v = v.lock().unwrap();
4103                    let inner = create_handler(parent, self_id);
4104                    let c = inner.into_counter().unwrap();
4105
4106                    c.increment_with_txn(txn, v.value)?;
4107
4108                    v.attached = c.attached_handler().cloned();
4109                    Ok(c)
4110                }
4111                MaybeDetached::Attached(a) => {
4112                    let new_inner = create_handler(a, self_id);
4113                    let ans = new_inner.into_counter().unwrap();
4114                    let delta = *self.get_value().as_double().unwrap();
4115                    ans.increment_with_txn(txn, delta)?;
4116                    Ok(ans)
4117                }
4118            }
4119        }
4120
4121        fn get_attached(&self) -> Option<Self> {
4122            match &self.inner {
4123                MaybeDetached::Attached(a) => Some(Self {
4124                    inner: MaybeDetached::Attached(a.clone()),
4125                }),
4126                MaybeDetached::Detached(_) => None,
4127            }
4128        }
4129
4130        fn doc(&self) -> Option<crate::LoroDoc> {
4131            match &self.inner {
4132                MaybeDetached::Detached(_) => None,
4133                MaybeDetached::Attached(a) => Some(a.doc()),
4134            }
4135        }
4136    }
4137}
4138
4139#[cfg(test)]
4140mod test {
4141
4142    use super::{HandlerTrait, TextDelta};
4143    use crate::state::TreeParentId;
4144    use crate::version::Frontiers;
4145    use crate::LoroDoc;
4146    use crate::{fx_map, ToJson};
4147    use loro_common::ID;
4148    use serde_json::json;
4149
4150    #[test]
4151    fn import() {
4152        let loro = LoroDoc::new();
4153        loro.set_peer_id(1).unwrap();
4154        let loro2 = LoroDoc::new();
4155        loro2.set_peer_id(2).unwrap();
4156
4157        let mut txn = loro.txn().unwrap();
4158        let text = txn.get_text("hello");
4159        text.insert_with_txn(&mut txn, 0, "hello").unwrap();
4160        txn.commit().unwrap();
4161        let exported = loro.export_from(&Default::default());
4162        loro2.import(&exported).unwrap();
4163        let mut txn = loro2.txn().unwrap();
4164        let text = txn.get_text("hello");
4165        assert_eq!(&**text.get_value().as_string().unwrap(), "hello");
4166        text.insert_with_txn(&mut txn, 5, " world").unwrap();
4167        assert_eq!(&**text.get_value().as_string().unwrap(), "hello world");
4168        txn.commit().unwrap();
4169        loro.import(&loro2.export_from(&Default::default()))
4170            .unwrap();
4171        let txn = loro.txn().unwrap();
4172        let text = txn.get_text("hello");
4173        assert_eq!(&**text.get_value().as_string().unwrap(), "hello world");
4174    }
4175
4176    #[test]
4177    fn richtext_handler() {
4178        let loro = LoroDoc::new();
4179        loro.set_peer_id(1).unwrap();
4180        let loro2 = LoroDoc::new();
4181        loro2.set_peer_id(2).unwrap();
4182
4183        let mut txn = loro.txn().unwrap();
4184        let text = txn.get_text("hello");
4185        text.insert_with_txn(&mut txn, 0, "hello").unwrap();
4186        txn.commit().unwrap();
4187        let exported = loro.export_from(&Default::default());
4188
4189        loro2.import(&exported).unwrap();
4190        let mut txn = loro2.txn().unwrap();
4191        let text = txn.get_text("hello");
4192        assert_eq!(&**text.get_value().as_string().unwrap(), "hello");
4193        text.insert_with_txn(&mut txn, 5, " world").unwrap();
4194        assert_eq!(&**text.get_value().as_string().unwrap(), "hello world");
4195        txn.commit().unwrap();
4196
4197        loro.import(&loro2.export_from(&Default::default()))
4198            .unwrap();
4199        let txn = loro.txn().unwrap();
4200        let text = txn.get_text("hello");
4201        assert_eq!(&**text.get_value().as_string().unwrap(), "hello world");
4202        txn.commit().unwrap();
4203
4204        // test checkout
4205        loro.checkout(&Frontiers::from_id(ID::new(2, 1))).unwrap();
4206        assert_eq!(&**text.get_value().as_string().unwrap(), "hello w");
4207    }
4208
4209    #[test]
4210    fn richtext_handler_concurrent() {
4211        let loro = LoroDoc::new();
4212        let mut txn = loro.txn().unwrap();
4213        let handler = loro.get_text("richtext");
4214        handler.insert_with_txn(&mut txn, 0, "hello").unwrap();
4215        txn.commit().unwrap();
4216        for i in 0..100 {
4217            let new_loro = LoroDoc::new();
4218            new_loro
4219                .import(&loro.export_from(&Default::default()))
4220                .unwrap();
4221            let mut txn = new_loro.txn().unwrap();
4222            let handler = new_loro.get_text("richtext");
4223            handler
4224                .insert_with_txn(&mut txn, i % 5, &i.to_string())
4225                .unwrap();
4226            txn.commit().unwrap();
4227            loro.import(&new_loro.export_from(&loro.oplog_vv()))
4228                .unwrap();
4229        }
4230    }
4231
4232    #[test]
4233    fn richtext_handler_mark() {
4234        let loro = LoroDoc::new_auto_commit();
4235        let handler = loro.get_text("richtext");
4236        handler.insert(0, "hello world").unwrap();
4237        handler.mark(0, 5, "bold", true.into()).unwrap();
4238        loro.commit_then_renew();
4239
4240        // assert has bold
4241        let value = handler.get_richtext_value();
4242        assert_eq!(value[0]["insert"], "hello".into());
4243        let meta = value[0]["attributes"].as_map().unwrap();
4244        assert_eq!(meta.len(), 1);
4245        meta.get("bold").unwrap();
4246
4247        let loro2 = LoroDoc::new_auto_commit();
4248        loro2
4249            .import(&loro.export_from(&Default::default()))
4250            .unwrap();
4251        let handler2 = loro2.get_text("richtext");
4252        assert_eq!(&**handler2.get_value().as_string().unwrap(), "hello world");
4253
4254        // assert has bold
4255        let value = handler2.get_richtext_value();
4256        assert_eq!(value[0]["insert"], "hello".into());
4257        let meta = value[0]["attributes"].as_map().unwrap();
4258        assert_eq!(meta.len(), 1);
4259        meta.get("bold").unwrap();
4260
4261        // insert after bold should be bold
4262        {
4263            handler2.insert(5, " new").unwrap();
4264            let value = handler2.get_richtext_value();
4265            assert_eq!(
4266                value.to_json_value(),
4267                serde_json::json!([
4268                    {"insert": "hello new", "attributes": {"bold": true}},
4269                    {"insert": " world"}
4270                ])
4271            );
4272        }
4273    }
4274
4275    #[test]
4276    fn richtext_snapshot() {
4277        let loro = LoroDoc::new();
4278        let mut txn = loro.txn().unwrap();
4279        let handler = loro.get_text("richtext");
4280        handler.insert_with_txn(&mut txn, 0, "hello world").unwrap();
4281        handler
4282            .mark_with_txn(&mut txn, 0, 5, "bold", true.into(), false)
4283            .unwrap();
4284        txn.commit().unwrap();
4285
4286        let loro2 = LoroDoc::new();
4287        loro2.import(&loro.export_snapshot().unwrap()).unwrap();
4288        let handler2 = loro2.get_text("richtext");
4289        assert_eq!(
4290            handler2.get_richtext_value().to_json_value(),
4291            serde_json::json!([
4292                {"insert": "hello", "attributes": {"bold": true}},
4293                {"insert": " world"}
4294            ])
4295        );
4296    }
4297
4298    #[test]
4299    fn tree_meta() {
4300        let loro = LoroDoc::new_auto_commit();
4301        loro.set_peer_id(1).unwrap();
4302        let tree = loro.get_tree("root");
4303        let id = tree.create(TreeParentId::Root).unwrap();
4304        let meta = tree.get_meta(id).unwrap();
4305        meta.insert("a", 123).unwrap();
4306        loro.commit_then_renew();
4307        let meta = tree.get_meta(id).unwrap();
4308        assert_eq!(meta.get("a").unwrap(), 123.into());
4309        assert_eq!(
4310            r#"[{"parent":null,"meta":{"a":123},"id":"0@1","index":0,"children":[],"fractional_index":"80"}]"#,
4311            tree.get_deep_value().to_json()
4312        );
4313        let bytes = loro.export_snapshot().unwrap();
4314        let loro2 = LoroDoc::new();
4315        loro2.import(&bytes).unwrap();
4316    }
4317
4318    #[test]
4319    fn tree_meta_event() {
4320        use std::sync::Arc;
4321        let loro = LoroDoc::new_auto_commit();
4322        let tree = loro.get_tree("root");
4323        let text = loro.get_text("text");
4324
4325        let id = tree.create(TreeParentId::Root).unwrap();
4326        let meta = tree.get_meta(id).unwrap();
4327        meta.insert("a", 1).unwrap();
4328        text.insert(0, "abc").unwrap();
4329        let _id2 = tree.create(TreeParentId::Root).unwrap();
4330        meta.insert("b", 2).unwrap();
4331
4332        let loro2 = LoroDoc::new_auto_commit();
4333        let _g = loro2.subscribe_root(Arc::new(|e| {
4334            println!("{} {:?} ", e.event_meta.by, e.event_meta.diff)
4335        }));
4336        loro2.import(&loro.export_from(&loro2.oplog_vv())).unwrap();
4337        assert_eq!(loro.get_deep_value(), loro2.get_deep_value());
4338    }
4339
4340    #[test]
4341    fn richtext_apply_delta() {
4342        let loro = LoroDoc::new_auto_commit();
4343        let text = loro.get_text("text");
4344        text.apply_delta(&[TextDelta::Insert {
4345            insert: "Hello World!".into(),
4346            attributes: None,
4347        }])
4348        .unwrap();
4349        dbg!(text.get_richtext_value());
4350        text.apply_delta(&[
4351            TextDelta::Retain {
4352                retain: 6,
4353                attributes: Some(fx_map!("italic".into() => loro_common::LoroValue::Bool(true))),
4354            },
4355            TextDelta::Insert {
4356                insert: "New ".into(),
4357                attributes: Some(fx_map!("bold".into() => loro_common::LoroValue::Bool(true))),
4358            },
4359        ])
4360        .unwrap();
4361        dbg!(text.get_richtext_value());
4362        loro.commit_then_renew();
4363        assert_eq!(
4364            text.get_richtext_value().to_json_value(),
4365            json!([
4366                {"insert": "Hello ", "attributes": {"italic": true}},
4367                {"insert": "New ", "attributes": {"bold": true}},
4368                {"insert": "World!"}
4369
4370            ])
4371        )
4372    }
4373}