loro_internal/
state.rs

1use std::{
2    borrow::Cow,
3    io::Write,
4    sync::{
5        atomic::{AtomicU64, Ordering},
6        Arc, Mutex, RwLock, Weak,
7    },
8};
9
10use container_store::ContainerStore;
11use dead_containers_cache::DeadContainersCache;
12use enum_as_inner::EnumAsInner;
13use enum_dispatch::enum_dispatch;
14use fxhash::{FxHashMap, FxHashSet};
15use itertools::Itertools;
16use loro_common::{ContainerID, LoroError, LoroResult, TreeID};
17use loro_delta::DeltaItem;
18use tracing::{info_span, instrument, warn};
19
20use crate::{
21    configure::{Configure, DefaultRandom, SecureRandomGenerator},
22    container::{idx::ContainerIdx, richtext::config::StyleConfigMap, ContainerIdRaw},
23    cursor::Cursor,
24    delta::TreeExternalDiff,
25    diff_calc::{DiffCalculator, DiffMode},
26    encoding::{StateSnapshotDecodeContext, StateSnapshotEncoder},
27    event::{Diff, EventTriggerKind, Index, InternalContainerDiff, InternalDiff},
28    fx_map,
29    handler::ValueOrHandler,
30    id::PeerID,
31    op::{Op, RawOp},
32    version::Frontiers,
33    ContainerDiff, ContainerType, DocDiff, InternalString, LoroDocInner, LoroValue, OpLog,
34};
35
36pub(crate) mod analyzer;
37pub(crate) mod container_store;
38#[cfg(feature = "counter")]
39mod counter_state;
40mod dead_containers_cache;
41mod list_state;
42mod map_state;
43mod movable_list_state;
44mod richtext_state;
45mod tree_state;
46mod unknown_state;
47
48pub(crate) use self::movable_list_state::{IndexType, MovableListState};
49pub(crate) use container_store::GcStore;
50pub(crate) use list_state::ListState;
51pub(crate) use map_state::MapState;
52pub(crate) use richtext_state::RichtextState;
53pub(crate) use tree_state::FiIfNotConfigured;
54pub(crate) use tree_state::{get_meta_value, FractionalIndexGenResult, NodePosition, TreeState};
55pub use tree_state::{TreeNode, TreeNodeWithChildren, TreeParentId};
56
57use self::{container_store::ContainerWrapper, unknown_state::UnknownState};
58
59#[cfg(feature = "counter")]
60use self::counter_state::CounterState;
61
62use super::{arena::SharedArena, event::InternalDocDiff};
63
64pub struct DocState {
65    pub(super) peer: Arc<AtomicU64>,
66
67    pub(super) frontiers: Frontiers,
68    // pub(super) states: FxHashMap<ContainerIdx, State>,
69    pub(super) store: ContainerStore,
70    pub(super) arena: SharedArena,
71    pub(crate) config: Configure,
72    // resolve event stuff
73    doc: Weak<LoroDocInner>,
74    // txn related stuff
75    in_txn: bool,
76    changed_idx_in_txn: FxHashSet<ContainerIdx>,
77
78    // diff related stuff
79    event_recorder: EventRecorder,
80
81    dead_containers_cache: DeadContainersCache,
82}
83
84impl std::fmt::Debug for DocState {
85    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
86        f.debug_struct("DocState")
87            .field("peer", &self.peer)
88            .finish()
89    }
90}
91
92#[derive(Clone, Copy)]
93pub(crate) struct ContainerCreationContext<'a> {
94    pub configure: &'a Configure,
95    pub peer: PeerID,
96}
97
98pub(crate) struct DiffApplyContext<'a> {
99    pub mode: DiffMode,
100    pub doc: &'a Weak<LoroDocInner>,
101}
102
103pub(crate) trait FastStateSnapshot {
104    fn encode_snapshot_fast<W: Write>(&mut self, w: W);
105    fn decode_value(bytes: &[u8]) -> LoroResult<(LoroValue, &[u8])>;
106    fn decode_snapshot_fast(
107        idx: ContainerIdx,
108        v: (LoroValue, &[u8]),
109        ctx: ContainerCreationContext,
110    ) -> LoroResult<Self>
111    where
112        Self: Sized;
113}
114
115#[derive(Debug, Clone, Default)]
116pub(crate) struct ApplyLocalOpReturn {
117    pub deleted_containers: Vec<ContainerID>,
118}
119
120#[enum_dispatch]
121pub(crate) trait ContainerState {
122    fn container_idx(&self) -> ContainerIdx;
123    fn estimate_size(&self) -> usize;
124
125    fn is_state_empty(&self) -> bool;
126
127    #[must_use]
128    fn apply_diff_and_convert(&mut self, diff: InternalDiff, ctx: DiffApplyContext) -> Diff;
129
130    fn apply_diff(&mut self, diff: InternalDiff, ctx: DiffApplyContext);
131
132    fn apply_local_op(&mut self, raw_op: &RawOp, op: &Op) -> LoroResult<ApplyLocalOpReturn>;
133    /// Convert a state to a diff, such that an empty state will be transformed into the same as this state when it's applied.
134    fn to_diff(&mut self, doc: &Weak<LoroDocInner>) -> Diff;
135
136    fn get_value(&mut self) -> LoroValue;
137
138    /// Get the index of the child container
139    #[allow(unused)]
140    fn get_child_index(&self, id: &ContainerID) -> Option<Index>;
141
142    #[allow(unused)]
143    fn contains_child(&self, id: &ContainerID) -> bool;
144
145    #[allow(unused)]
146    fn get_child_containers(&self) -> Vec<ContainerID>;
147
148    /// Encode the ops and the blob that can be used to restore the state to the current state.
149    ///
150    /// State will use the provided encoder to encode the ops and export a blob.
151    /// The ops should be encoded into the snapshot as well as the blob.
152    /// The users then can use the ops and the blob to restore the state to the current state.
153    fn encode_snapshot(&self, encoder: StateSnapshotEncoder) -> Vec<u8>;
154
155    /// Restore the state to the state represented by the ops and the blob that exported by `get_snapshot_ops`
156    fn import_from_snapshot_ops(&mut self, ctx: StateSnapshotDecodeContext) -> LoroResult<()>;
157    fn fork(&self, config: &Configure) -> Self;
158}
159
160impl<T: FastStateSnapshot> FastStateSnapshot for Box<T> {
161    fn encode_snapshot_fast<W: Write>(&mut self, w: W) {
162        self.as_mut().encode_snapshot_fast(w)
163    }
164
165    fn decode_value(bytes: &[u8]) -> LoroResult<(LoroValue, &[u8])> {
166        T::decode_value(bytes)
167    }
168
169    fn decode_snapshot_fast(
170        idx: ContainerIdx,
171        v: (LoroValue, &[u8]),
172        ctx: ContainerCreationContext,
173    ) -> LoroResult<Self>
174    where
175        Self: Sized,
176    {
177        T::decode_snapshot_fast(idx, v, ctx).map(|x| Box::new(x))
178    }
179}
180
181impl<T: ContainerState> ContainerState for Box<T> {
182    fn container_idx(&self) -> ContainerIdx {
183        self.as_ref().container_idx()
184    }
185
186    fn estimate_size(&self) -> usize {
187        self.as_ref().estimate_size()
188    }
189
190    fn is_state_empty(&self) -> bool {
191        self.as_ref().is_state_empty()
192    }
193
194    fn apply_diff_and_convert(&mut self, diff: InternalDiff, ctx: DiffApplyContext) -> Diff {
195        self.as_mut().apply_diff_and_convert(diff, ctx)
196    }
197
198    fn apply_diff(&mut self, diff: InternalDiff, ctx: DiffApplyContext) {
199        self.as_mut().apply_diff(diff, ctx)
200    }
201
202    fn apply_local_op(&mut self, raw_op: &RawOp, op: &Op) -> LoroResult<ApplyLocalOpReturn> {
203        self.as_mut().apply_local_op(raw_op, op)
204    }
205
206    #[doc = r" Convert a state to a diff, such that an empty state will be transformed into the same as this state when it's applied."]
207    fn to_diff(&mut self, doc: &Weak<LoroDocInner>) -> Diff {
208        self.as_mut().to_diff(doc)
209    }
210
211    fn get_value(&mut self) -> LoroValue {
212        self.as_mut().get_value()
213    }
214
215    #[doc = r" Get the index of the child container"]
216    #[allow(unused)]
217    fn get_child_index(&self, id: &ContainerID) -> Option<Index> {
218        self.as_ref().get_child_index(id)
219    }
220
221    fn contains_child(&self, id: &ContainerID) -> bool {
222        self.as_ref().contains_child(id)
223    }
224
225    #[allow(unused)]
226    fn get_child_containers(&self) -> Vec<ContainerID> {
227        self.as_ref().get_child_containers()
228    }
229
230    #[doc = r" Encode the ops and the blob that can be used to restore the state to the current state."]
231    #[doc = r""]
232    #[doc = r" State will use the provided encoder to encode the ops and export a blob."]
233    #[doc = r" The ops should be encoded into the snapshot as well as the blob."]
234    #[doc = r" The users then can use the ops and the blob to restore the state to the current state."]
235    fn encode_snapshot(&self, encoder: StateSnapshotEncoder) -> Vec<u8> {
236        self.as_ref().encode_snapshot(encoder)
237    }
238
239    #[doc = r" Restore the state to the state represented by the ops and the blob that exported by `get_snapshot_ops`"]
240    fn import_from_snapshot_ops(&mut self, ctx: StateSnapshotDecodeContext) -> LoroResult<()> {
241        self.as_mut().import_from_snapshot_ops(ctx)
242    }
243
244    fn fork(&self, config: &Configure) -> Self {
245        Box::new(self.as_ref().fork(config))
246    }
247}
248
249#[allow(clippy::enum_variant_names)]
250#[enum_dispatch(ContainerState)]
251#[derive(EnumAsInner, Debug)]
252pub enum State {
253    ListState(Box<ListState>),
254    MovableListState(Box<MovableListState>),
255    MapState(Box<MapState>),
256    RichtextState(Box<RichtextState>),
257    TreeState(Box<TreeState>),
258    #[cfg(feature = "counter")]
259    CounterState(Box<counter_state::CounterState>),
260    UnknownState(UnknownState),
261}
262
263impl From<ListState> for State {
264    fn from(s: ListState) -> Self {
265        Self::ListState(Box::new(s))
266    }
267}
268
269impl From<RichtextState> for State {
270    fn from(s: RichtextState) -> Self {
271        Self::RichtextState(Box::new(s))
272    }
273}
274
275impl From<MovableListState> for State {
276    fn from(s: MovableListState) -> Self {
277        Self::MovableListState(Box::new(s))
278    }
279}
280
281impl From<MapState> for State {
282    fn from(s: MapState) -> Self {
283        Self::MapState(Box::new(s))
284    }
285}
286
287impl From<TreeState> for State {
288    fn from(s: TreeState) -> Self {
289        Self::TreeState(Box::new(s))
290    }
291}
292
293#[cfg(feature = "counter")]
294impl From<CounterState> for State {
295    fn from(s: CounterState) -> Self {
296        Self::CounterState(Box::new(s))
297    }
298}
299
300impl State {
301    pub fn new_list(idx: ContainerIdx) -> Self {
302        Self::ListState(Box::new(ListState::new(idx)))
303    }
304
305    pub fn new_map(idx: ContainerIdx) -> Self {
306        Self::MapState(Box::new(MapState::new(idx)))
307    }
308
309    pub fn new_richtext(idx: ContainerIdx, config: Arc<RwLock<StyleConfigMap>>) -> Self {
310        Self::RichtextState(Box::new(RichtextState::new(idx, config)))
311    }
312
313    pub fn new_tree(idx: ContainerIdx, peer: PeerID) -> Self {
314        Self::TreeState(Box::new(TreeState::new(idx, peer)))
315    }
316
317    pub fn new_unknown(idx: ContainerIdx) -> Self {
318        Self::UnknownState(UnknownState::new(idx))
319    }
320
321    pub fn encode_snapshot_fast<W: Write>(&mut self, mut w: W) {
322        match self {
323            State::ListState(s) => s.encode_snapshot_fast(&mut w),
324            State::MovableListState(s) => s.encode_snapshot_fast(&mut w),
325            State::MapState(s) => s.encode_snapshot_fast(&mut w),
326            State::RichtextState(s) => s.encode_snapshot_fast(&mut w),
327            State::TreeState(s) => s.encode_snapshot_fast(&mut w),
328            #[cfg(feature = "counter")]
329            State::CounterState(s) => s.encode_snapshot_fast(&mut w),
330            State::UnknownState(s) => s.encode_snapshot_fast(&mut w),
331        }
332    }
333
334    pub fn fork(&self, config: &Configure) -> Self {
335        match self {
336            State::ListState(list_state) => State::ListState(list_state.fork(config)),
337            State::MovableListState(movable_list_state) => {
338                State::MovableListState(movable_list_state.fork(config))
339            }
340            State::MapState(map_state) => State::MapState(map_state.fork(config)),
341            State::RichtextState(richtext_state) => {
342                State::RichtextState(richtext_state.fork(config))
343            }
344            State::TreeState(tree_state) => State::TreeState(tree_state.fork(config)),
345            #[cfg(feature = "counter")]
346            State::CounterState(counter_state) => State::CounterState(counter_state.fork(config)),
347            State::UnknownState(unknown_state) => State::UnknownState(unknown_state.fork(config)),
348        }
349    }
350}
351
352impl DocState {
353    #[inline]
354    pub fn new_arc(
355        doc: Weak<LoroDocInner>,
356        arena: SharedArena,
357        config: Configure,
358    ) -> Arc<Mutex<Self>> {
359        let peer = DefaultRandom.next_u64();
360        // TODO: maybe we should switch to certain version in oplog?
361
362        let peer = Arc::new(AtomicU64::new(peer));
363        Arc::new(Mutex::new(Self {
364            store: ContainerStore::new(arena.clone(), config.clone(), peer.clone()),
365            peer,
366            arena,
367            frontiers: Frontiers::default(),
368            doc,
369            config,
370            in_txn: false,
371            changed_idx_in_txn: FxHashSet::default(),
372            event_recorder: Default::default(),
373            dead_containers_cache: Default::default(),
374        }))
375    }
376
377    pub fn fork_with_new_peer_id(
378        &mut self,
379        doc: Weak<LoroDocInner>,
380        arena: SharedArena,
381        config: Configure,
382    ) -> Arc<Mutex<Self>> {
383        let peer = Arc::new(AtomicU64::new(DefaultRandom.next_u64()));
384        let store = self.store.fork(arena.clone(), peer.clone(), config.clone());
385        Arc::new(Mutex::new(Self {
386            peer,
387            frontiers: self.frontiers.clone(),
388            store,
389            arena,
390            config,
391            doc,
392            in_txn: false,
393            changed_idx_in_txn: FxHashSet::default(),
394            event_recorder: Default::default(),
395            dead_containers_cache: Default::default(),
396        }))
397    }
398
399    pub fn start_recording(&mut self) {
400        if self.is_recording() {
401            return;
402        }
403
404        self.event_recorder.recording_diff = true;
405        self.event_recorder.diff_start_version = Some(self.frontiers.clone());
406    }
407
408    #[inline(always)]
409    pub fn stop_and_clear_recording(&mut self) {
410        self.event_recorder = Default::default();
411    }
412
413    #[inline(always)]
414    pub fn is_recording(&self) -> bool {
415        self.event_recorder.recording_diff
416    }
417
418    pub fn refresh_peer_id(&mut self) {
419        self.peer.store(
420            DefaultRandom.next_u64(),
421            std::sync::atomic::Ordering::Relaxed,
422        );
423    }
424
425    /// Take all the diffs that are recorded and convert them to events.
426    pub fn take_events(&mut self) -> Vec<DocDiff> {
427        if !self.is_recording() {
428            return vec![];
429        }
430
431        self.convert_current_batch_diff_into_event();
432        std::mem::take(&mut self.event_recorder.events)
433    }
434
435    /// Record the next diff.
436    /// Caller should call [pre_txn] before calling this.
437    ///
438    /// # Panic
439    ///
440    /// Panic when the diff cannot be merged with the previous diff.
441    /// Caller should call [pre_txn] before calling this to avoid panic.
442    fn record_diff(&mut self, diff: InternalDocDiff) {
443        if !self.event_recorder.recording_diff || diff.diff.is_empty() {
444            return;
445        }
446
447        let Some(last_diff) = self.event_recorder.diffs.last_mut() else {
448            self.event_recorder.diffs.push(diff.into_owned());
449            return;
450        };
451
452        if last_diff.can_merge(&diff) {
453            self.event_recorder.diffs.push(diff.into_owned());
454            return;
455        }
456
457        panic!("should call pre_txn before record_diff")
458    }
459
460    /// This should be called when DocState is going to apply a transaction / a diff.
461    fn pre_txn(&mut self, next_origin: InternalString, next_trigger: EventTriggerKind) {
462        if !self.is_recording() {
463            return;
464        }
465
466        let Some(last_diff) = self.event_recorder.diffs.last() else {
467            return;
468        };
469
470        if last_diff.origin == next_origin && last_diff.by == next_trigger {
471            return;
472        }
473
474        // current diff batch cannot merge with the incoming diff,
475        // need to convert all the current diffs into event
476        self.convert_current_batch_diff_into_event()
477    }
478
479    fn convert_current_batch_diff_into_event(&mut self) {
480        let recorder = &mut self.event_recorder;
481        if recorder.diffs.is_empty() {
482            return;
483        }
484
485        let diffs = std::mem::take(&mut recorder.diffs);
486        let start = recorder.diff_start_version.take().unwrap();
487        recorder.diff_start_version = Some((*diffs.last().unwrap().new_version).to_owned());
488        let event = self.diffs_to_event(diffs, start);
489        self.event_recorder.events.push(event);
490    }
491
492    /// Change the peer id of this doc state.
493    /// It changes the peer id for the future txn on this AppState
494    #[inline]
495    pub fn set_peer_id(&mut self, peer: PeerID) {
496        self.peer.store(peer, std::sync::atomic::Ordering::Relaxed);
497    }
498
499    pub fn peer_id(&self) -> PeerID {
500        self.peer.load(std::sync::atomic::Ordering::Relaxed)
501    }
502
503    /// It's expected that diff only contains [`InternalDiff`]
504    ///
505    #[instrument(skip_all)]
506    pub(crate) fn apply_diff(&mut self, mut diff: InternalDocDiff<'static>, diff_mode: DiffMode) {
507        if self.in_txn {
508            panic!("apply_diff should not be called in a transaction");
509        }
510
511        match diff_mode {
512            DiffMode::Checkout => {
513                self.dead_containers_cache.clear();
514            }
515            _ => {
516                self.dead_containers_cache.clear_alive();
517            }
518        }
519
520        let is_recording = self.is_recording();
521        self.pre_txn(diff.origin.clone(), diff.by);
522        let Cow::Owned(mut diffs) = std::mem::take(&mut diff.diff) else {
523            unreachable!()
524        };
525
526        // # Revival
527        //
528        // A Container, if it is deleted from its parent Container, will still exist
529        // in the internal state of Loro;  whereas on the user side, a tree structure
530        // is maintained following Events, and at this point, the corresponding state
531        // is considered deleted.
532        //
533        // Sometimes, this "pseudo-dead" Container may be revived (for example, through
534        // backtracking or parallel editing),  and the user side should receive an Event
535        // that restores the consistency between the revived Container and the  internal
536        // state of Loro. This Event is required to restore the pseudo-dead  Container
537        // State to its current state on Loro, and we refer to this process as "revival".
538        //
539        // Revival occurs during the application of the internal diff, and this operation
540        // is necessary when it needs to be converted into an external Event.
541        //
542        // We can utilize the output of the Diff to determine which child nodes should be revived.
543        //
544        // For nodes that are to be revived, we can disregard the Events output by their
545        // round of apply_diff_and_convert,  and instead, directly convert their state into
546        // an Event once their application is complete.
547        //
548        // Suppose A is revived and B is A's child, and B also needs to be revived; therefore,
549        // we should process each level alternately.
550
551        // We need to ensure diff is processed in order
552        diffs.sort_by_cached_key(|diff| self.arena.get_depth(diff.idx));
553        let mut to_revive_in_next_layer: FxHashSet<ContainerIdx> = FxHashSet::default();
554        let mut to_revive_in_this_layer: FxHashSet<ContainerIdx> = FxHashSet::default();
555        let mut last_depth = 0;
556        let len = diffs.len();
557        for mut diff in std::mem::replace(&mut diffs, Vec::with_capacity(len)) {
558            let Some(depth) = self.arena.get_depth(diff.idx) else {
559                warn!("{:?} is not in arena. It could be a dangling container that was deleted before the shallow start version.", self.arena.idx_to_id(diff.idx));
560                continue;
561            };
562            let this_depth = depth.get();
563            while this_depth > last_depth {
564                // Clear `to_revive` when we are going to process a new level
565                // so that we can process the revival of the next level
566                let to_create = std::mem::take(&mut to_revive_in_this_layer);
567                to_revive_in_this_layer = std::mem::take(&mut to_revive_in_next_layer);
568                for new in to_create {
569                    let state = self.store.get_or_create_mut(new);
570                    if state.is_state_empty() {
571                        continue;
572                    }
573
574                    let external_diff = state.to_diff(&self.doc);
575                    trigger_on_new_container(
576                        &external_diff,
577                        |cid| {
578                            to_revive_in_this_layer.insert(cid);
579                        },
580                        &self.arena,
581                    );
582
583                    diffs.push(InternalContainerDiff {
584                        idx: new,
585                        bring_back: true,
586                        is_container_deleted: false,
587                        diff: external_diff.into(),
588                        diff_mode: DiffMode::Checkout,
589                    });
590                }
591
592                last_depth += 1;
593            }
594
595            let idx = diff.idx;
596            let internal_diff = std::mem::take(&mut diff.diff);
597            match &internal_diff {
598                crate::event::DiffVariant::None => {
599                    if is_recording {
600                        let state = self.store.get_or_create_mut(diff.idx);
601                        let extern_diff = state.to_diff(&self.doc);
602                        trigger_on_new_container(
603                            &extern_diff,
604                            |cid| {
605                                to_revive_in_next_layer.insert(cid);
606                            },
607                            &self.arena,
608                        );
609                        diff.diff = extern_diff.into();
610                    }
611                }
612                crate::event::DiffVariant::Internal(_) => {
613                    let cid = self.arena.idx_to_id(idx).unwrap();
614                    info_span!("apply diff on", container_id = ?cid).in_scope(|| {
615                        if self.in_txn {
616                            self.changed_idx_in_txn.insert(idx);
617                        }
618                        let state = self.store.get_or_create_mut(idx);
619                        if is_recording {
620                            // process bring_back before apply
621                            let external_diff =
622                                if diff.bring_back || to_revive_in_this_layer.contains(&idx) {
623                                    state.apply_diff(
624                                        internal_diff.into_internal().unwrap(),
625                                        DiffApplyContext {
626                                            mode: diff.diff_mode,
627                                            doc: &self.doc,
628                                        },
629                                    );
630                                    state.to_diff(&self.doc)
631                                } else {
632                                    state.apply_diff_and_convert(
633                                        internal_diff.into_internal().unwrap(),
634                                        DiffApplyContext {
635                                            mode: diff.diff_mode,
636                                            doc: &self.doc,
637                                        },
638                                    )
639                                };
640                            trigger_on_new_container(
641                                &external_diff,
642                                |cid| {
643                                    to_revive_in_next_layer.insert(cid);
644                                },
645                                &self.arena,
646                            );
647                            diff.diff = external_diff.into();
648                        } else {
649                            state.apply_diff(
650                                internal_diff.into_internal().unwrap(),
651                                DiffApplyContext {
652                                    mode: diff.diff_mode,
653                                    doc: &self.doc,
654                                },
655                            );
656                        }
657                    });
658                }
659                crate::event::DiffVariant::External(_) => unreachable!(),
660            }
661
662            to_revive_in_this_layer.remove(&idx);
663            if !diff.diff.is_empty() {
664                diffs.push(diff);
665            }
666        }
667
668        // Revive the last several layers
669        while !to_revive_in_this_layer.is_empty() || !to_revive_in_next_layer.is_empty() {
670            let to_create = std::mem::take(&mut to_revive_in_this_layer);
671            for new in to_create {
672                let state = self.store.get_or_create_mut(new);
673                if state.is_state_empty() {
674                    continue;
675                }
676
677                let external_diff = state.to_diff(&self.doc);
678                trigger_on_new_container(
679                    &external_diff,
680                    |cid| {
681                        to_revive_in_next_layer.insert(cid);
682                    },
683                    &self.arena,
684                );
685
686                if !external_diff.is_empty() {
687                    diffs.push(InternalContainerDiff {
688                        idx: new,
689                        bring_back: true,
690                        is_container_deleted: false,
691                        diff: external_diff.into(),
692                        diff_mode: DiffMode::Checkout,
693                    });
694                }
695            }
696
697            to_revive_in_this_layer = std::mem::take(&mut to_revive_in_next_layer);
698        }
699
700        diff.diff = diffs.into();
701        self.frontiers = diff.new_version.clone().into_owned();
702        if self.is_recording() {
703            self.record_diff(diff)
704        }
705    }
706
707    pub fn apply_local_op(&mut self, raw_op: &RawOp, op: &Op) -> LoroResult<()> {
708        // set parent first, `MapContainer` will only be created for TreeID that does not contain
709        self.set_container_parent_by_raw_op(raw_op);
710        let state = self.store.get_or_create_mut(op.container);
711        if self.in_txn {
712            self.changed_idx_in_txn.insert(op.container);
713        }
714        let ret = state.apply_local_op(raw_op, op)?;
715        if !ret.deleted_containers.is_empty() {
716            self.dead_containers_cache.clear_alive();
717        }
718
719        Ok(())
720    }
721
722    pub(crate) fn start_txn(&mut self, origin: InternalString, trigger: EventTriggerKind) {
723        self.pre_txn(origin, trigger);
724        self.in_txn = true;
725    }
726
727    pub(crate) fn abort_txn(&mut self) {
728        self.in_txn = false;
729    }
730
731    pub fn iter_and_decode_all(&mut self) -> impl Iterator<Item = &mut State> {
732        self.store.iter_and_decode_all()
733    }
734
735    pub(crate) fn iter_all_containers_mut(
736        &mut self,
737    ) -> impl Iterator<Item = (&ContainerIdx, &mut ContainerWrapper)> {
738        self.store.iter_all_containers()
739    }
740
741    pub fn does_container_exist(&self, id: &ContainerID) -> bool {
742        // TODO: we may need a better way to handle this in the future when we need to enable fully lazy loading on state
743        self.arena.id_to_idx(id).is_some()
744    }
745
746    pub(crate) fn init_container(
747        &mut self,
748        cid: ContainerID,
749        decode_ctx: StateSnapshotDecodeContext,
750    ) -> LoroResult<()> {
751        let idx = self.arena.register_container(&cid);
752        let state = self.store.get_or_create_mut(idx);
753        state.import_from_snapshot_ops(decode_ctx)
754    }
755
756    pub(crate) fn init_unknown_container(&mut self, cid: ContainerID) {
757        let idx = self.arena.register_container(&cid);
758        self.store.get_or_create_imm(idx);
759    }
760
761    pub(crate) fn commit_txn(&mut self, new_frontiers: Frontiers, diff: Option<InternalDocDiff>) {
762        self.in_txn = false;
763        self.frontiers = new_frontiers;
764        if self.is_recording() {
765            self.record_diff(diff.unwrap());
766        }
767    }
768
769    #[inline]
770    pub(super) fn get_container_mut(&mut self, idx: ContainerIdx) -> Option<&mut State> {
771        self.store.get_container_mut(idx)
772    }
773
774    /// Ensure the container is created and will be encoded in the next `encode` call
775    #[inline]
776    pub(crate) fn ensure_container(&mut self, id: &ContainerID) {
777        self.store.ensure_container(id);
778    }
779
780    /// Ensure all alive containers are created in DocState and will be encoded in the next `encode` call
781    pub(crate) fn ensure_all_alive_containers(&mut self) -> FxHashSet<ContainerID> {
782        // TODO: PERF This can be optimized because we shouldn't need to call get_value for
783        // all the containers every time we export
784        let ans = self.get_all_alive_containers();
785        for id in ans.iter() {
786            self.ensure_container(id);
787        }
788
789        ans
790    }
791
792    pub(crate) fn get_value_by_idx(&mut self, container_idx: ContainerIdx) -> LoroValue {
793        self.store
794            .get_value(container_idx)
795            .unwrap_or_else(|| container_idx.get_type().default_value())
796    }
797
798    /// Set the state of the container with the given container idx.
799    /// This is only used for decode.
800    ///
801    /// # Panic
802    ///
803    /// If the state is not empty.
804    pub(super) fn init_with_states_and_version(
805        &mut self,
806        frontiers: Frontiers,
807        oplog: &OpLog,
808        unknown_containers: Vec<ContainerIdx>,
809        need_to_register_parent: bool,
810    ) {
811        self.pre_txn(Default::default(), EventTriggerKind::Import);
812        if need_to_register_parent {
813            for state in self.store.iter_and_decode_all() {
814                let idx = state.container_idx();
815                let s = state;
816                for child_id in s.get_child_containers() {
817                    let child_idx = self.arena.register_container(&child_id);
818                    self.arena.set_parent(child_idx, Some(idx));
819                }
820            }
821        }
822
823        if !unknown_containers.is_empty() {
824            let mut diff_calc = DiffCalculator::new(false);
825            let stack_vv;
826            let vv = if oplog.frontiers() == &frontiers {
827                oplog.vv()
828            } else {
829                stack_vv = oplog.dag().frontiers_to_vv(&frontiers);
830                stack_vv.as_ref().unwrap()
831            };
832
833            let (unknown_diffs, _diff_mode) = diff_calc.calc_diff_internal(
834                oplog,
835                &Default::default(),
836                &Default::default(),
837                vv,
838                &frontiers,
839                Some(&|idx| !idx.is_unknown() && unknown_containers.contains(&idx)),
840            );
841            self.apply_diff(
842                InternalDocDiff {
843                    origin: Default::default(),
844                    by: EventTriggerKind::Import,
845                    diff: unknown_diffs.into(),
846                    new_version: Cow::Owned(frontiers.clone()),
847                },
848                DiffMode::Checkout,
849            )
850        }
851
852        if self.is_recording() {
853            let diff: Vec<_> = self
854                .store
855                .iter_all_containers()
856                .map(|(&idx, state)| InternalContainerDiff {
857                    idx,
858                    bring_back: false,
859                    is_container_deleted: false,
860                    diff: state
861                        .get_state_mut(
862                            idx,
863                            ContainerCreationContext {
864                                configure: &self.config,
865                                peer: self.peer.load(Ordering::Relaxed),
866                            },
867                        )
868                        .to_diff(&self.doc)
869                        .into(),
870                    diff_mode: DiffMode::Checkout,
871                })
872                .collect();
873
874            self.record_diff(InternalDocDiff {
875                origin: Default::default(),
876                by: EventTriggerKind::Import,
877                diff: diff.into(),
878                new_version: Cow::Borrowed(&frontiers),
879            });
880        }
881
882        self.frontiers = frontiers;
883    }
884
885    /// id can be a str, ContainerID, or ContainerIdRaw.
886    /// if it's str it will use Root container, which will not be None
887    pub fn get_text<I: Into<ContainerIdRaw>>(
888        &mut self,
889        id: I,
890    ) -> Option<&mut richtext_state::RichtextState> {
891        let idx = self.id_to_idx(id, ContainerType::Text);
892        self.store
893            .get_or_create_mut(idx)
894            .as_richtext_state_mut()
895            .map(|x| &mut **x)
896    }
897
898    /// id can be a str, ContainerID, or ContainerIdRaw.
899    /// if it's str it will use Root container, which will not be None
900    #[allow(unused)]
901    pub(crate) fn get_tree<I: Into<ContainerIdRaw>>(&mut self, id: I) -> Option<&mut TreeState> {
902        let idx = self.id_to_idx(id, ContainerType::Tree);
903        self.store
904            .get_or_create_mut(idx)
905            .as_tree_state_mut()
906            .map(|x| &mut **x)
907    }
908
909    fn id_to_idx<I: Into<ContainerIdRaw>>(&mut self, id: I, kind: ContainerType) -> ContainerIdx {
910        let id: ContainerIdRaw = id.into();
911        let cid;
912        let idx = match id {
913            ContainerIdRaw::Root { name } => {
914                cid = crate::container::ContainerID::Root {
915                    name,
916                    container_type: kind,
917                };
918                Some(self.arena.register_container(&cid))
919            }
920            ContainerIdRaw::Normal { id: _ } => {
921                cid = id.with_type(kind);
922                self.arena.id_to_idx(&cid)
923            }
924        };
925
926        idx.unwrap()
927    }
928
929    #[inline(always)]
930    #[allow(unused)]
931    pub(crate) fn with_state<F, R>(&mut self, idx: ContainerIdx, f: F) -> R
932    where
933        F: FnOnce(&State) -> R,
934    {
935        let depth = self.arena.get_depth(idx).unwrap().get() as usize;
936        let state = self.store.get_or_create_imm(idx);
937        f(state)
938    }
939
940    #[inline(always)]
941    pub(crate) fn with_state_mut<F, R>(&mut self, idx: ContainerIdx, f: F) -> R
942    where
943        F: FnOnce(&mut State) -> R,
944    {
945        let state = self.store.get_or_create_mut(idx);
946        f(state)
947    }
948
949    pub(super) fn is_in_txn(&self) -> bool {
950        self.in_txn
951    }
952
953    pub fn can_import_snapshot(&self) -> bool {
954        !self.in_txn && self.arena.can_import_snapshot() && self.store.can_import_snapshot()
955    }
956
957    pub fn get_value(&self) -> LoroValue {
958        let roots = self.arena.root_containers();
959        let ans: loro_common::LoroMapValue = roots
960            .into_iter()
961            .map(|idx| {
962                let id = self.arena.idx_to_id(idx).unwrap();
963                let ContainerID::Root {
964                    name,
965                    container_type: _,
966                } = &id
967                else {
968                    unreachable!()
969                };
970                (name.to_string(), LoroValue::Container(id))
971            })
972            .collect();
973        LoroValue::Map(ans)
974    }
975
976    pub fn get_deep_value(&mut self) -> LoroValue {
977        let roots = self.arena.root_containers();
978        let mut ans = FxHashMap::with_capacity_and_hasher(roots.len(), Default::default());
979        for root_idx in roots {
980            let id = self.arena.idx_to_id(root_idx).unwrap();
981            match id {
982                loro_common::ContainerID::Root { name, .. } => {
983                    ans.insert(name.to_string(), self.get_container_deep_value(root_idx));
984                }
985                loro_common::ContainerID::Normal { .. } => {
986                    unreachable!()
987                }
988            }
989        }
990
991        LoroValue::Map(ans.into())
992    }
993
994    pub fn get_deep_value_with_id(&mut self) -> LoroValue {
995        let roots = self.arena.root_containers();
996        let mut ans = FxHashMap::with_capacity_and_hasher(roots.len(), Default::default());
997        for root_idx in roots {
998            let id = self.arena.idx_to_id(root_idx).unwrap();
999            match id.clone() {
1000                loro_common::ContainerID::Root { name, .. } => {
1001                    ans.insert(
1002                        name.to_string(),
1003                        self.get_container_deep_value_with_id(root_idx, Some(id)),
1004                    );
1005                }
1006                loro_common::ContainerID::Normal { .. } => {
1007                    unreachable!()
1008                }
1009            }
1010        }
1011
1012        LoroValue::Map(ans.into())
1013    }
1014
1015    pub fn get_all_container_value_flat(&mut self) -> LoroValue {
1016        let mut map = FxHashMap::default();
1017        self.store.iter_and_decode_all().for_each(|c| {
1018            let value = c.get_value();
1019            let cid = self.arena.idx_to_id(c.container_idx()).unwrap().to_string();
1020            map.insert(cid, value);
1021        });
1022
1023        LoroValue::Map(map.into())
1024    }
1025
1026    pub(crate) fn get_container_deep_value_with_id(
1027        &mut self,
1028        container: ContainerIdx,
1029        id: Option<ContainerID>,
1030    ) -> LoroValue {
1031        let id = id.unwrap_or_else(|| self.arena.idx_to_id(container).unwrap());
1032        let Some(state) = self.store.get_container_mut(container) else {
1033            return container.get_type().default_value();
1034        };
1035        let value = state.get_value();
1036        let cid_str = LoroValue::String(format!("idx:{}, id:{}", container.to_index(), id).into());
1037        match value {
1038            LoroValue::Container(_) => unreachable!(),
1039            LoroValue::List(mut list) => {
1040                if container.get_type() == ContainerType::Tree {
1041                    get_meta_value(list.make_mut(), self);
1042                } else {
1043                    if list.iter().all(|x| !x.is_container()) {
1044                        return LoroValue::Map(
1045                            (fx_map!(
1046                                "cid".into() => cid_str,
1047                                "value".into() =>  LoroValue::List(list)
1048                            ))
1049                            .into(),
1050                        );
1051                    }
1052
1053                    let list_mut = list.make_mut();
1054                    for item in list_mut.iter_mut() {
1055                        if item.is_container() {
1056                            let container = item.as_container().unwrap();
1057                            let container_idx = self.arena.register_container(container);
1058                            let value = self.get_container_deep_value_with_id(
1059                                container_idx,
1060                                Some(container.clone()),
1061                            );
1062                            *item = value;
1063                        }
1064                    }
1065                }
1066                LoroValue::Map(
1067                    (fx_map!(
1068                        "cid".into() => cid_str,
1069                        "value".into() => LoroValue::List(list)
1070                    ))
1071                    .into(),
1072                )
1073            }
1074            LoroValue::Map(mut map) => {
1075                let map_mut = map.make_mut();
1076                for (_key, value) in map_mut.iter_mut() {
1077                    if value.is_container() {
1078                        let container = value.as_container().unwrap();
1079                        let container_idx = self.arena.register_container(container);
1080                        let new_value = self.get_container_deep_value_with_id(
1081                            container_idx,
1082                            Some(container.clone()),
1083                        );
1084                        *value = new_value;
1085                    }
1086                }
1087
1088                LoroValue::Map(
1089                    (fx_map!(
1090                        "cid".into() => cid_str,
1091                        "value".into() => LoroValue::Map(map)
1092                    ))
1093                    .into(),
1094                )
1095            }
1096            _ => LoroValue::Map(
1097                (fx_map!(
1098                    "cid".into() => cid_str,
1099                    "value".into() => value
1100                ))
1101                .into(),
1102            ),
1103        }
1104    }
1105
1106    pub fn get_container_deep_value(&mut self, container: ContainerIdx) -> LoroValue {
1107        let Some(value) = self.store.get_value(container) else {
1108            return container.get_type().default_value();
1109        };
1110        match value {
1111            LoroValue::Container(_) => unreachable!(),
1112            LoroValue::List(mut list) => {
1113                if container.get_type() == ContainerType::Tree {
1114                    // Each tree node has an associated map container to represent
1115                    // the metadata of this node. When the user get the deep value,
1116                    // we need to add a field named `meta` to the tree node,
1117                    // whose value is deep value of map container.
1118                    get_meta_value(list.make_mut(), self);
1119                } else {
1120                    if list.iter().all(|x| !x.is_container()) {
1121                        return LoroValue::List(list);
1122                    }
1123
1124                    let list_mut = list.make_mut();
1125                    for item in list_mut.iter_mut() {
1126                        if item.is_container() {
1127                            let container = item.as_container().unwrap();
1128                            let container_idx = self.arena.register_container(container);
1129                            let value = self.get_container_deep_value(container_idx);
1130                            *item = value;
1131                        }
1132                    }
1133                }
1134                LoroValue::List(list)
1135            }
1136            LoroValue::Map(mut map) => {
1137                if map.iter().all(|x| !x.1.is_container()) {
1138                    return LoroValue::Map(map);
1139                }
1140
1141                let map_mut = map.make_mut();
1142                for (_key, value) in map_mut.iter_mut() {
1143                    if value.is_container() {
1144                        let container = value.as_container().unwrap();
1145                        let container_idx = self.arena.register_container(container);
1146                        let new_value = self.get_container_deep_value(container_idx);
1147                        *value = new_value;
1148                    }
1149                }
1150                LoroValue::Map(map)
1151            }
1152            _ => value,
1153        }
1154    }
1155
1156    pub(crate) fn get_all_alive_containers(&mut self) -> FxHashSet<ContainerID> {
1157        let mut ans = FxHashSet::default();
1158        let mut to_visit = self
1159            .arena
1160            .root_containers()
1161            .iter()
1162            .map(|x| self.arena.get_container_id(*x).unwrap())
1163            .collect_vec();
1164
1165        while let Some(id) = to_visit.pop() {
1166            self.get_alive_children_of(&id, &mut to_visit);
1167            ans.insert(id);
1168        }
1169
1170        ans
1171    }
1172
1173    pub(crate) fn get_alive_children_of(&mut self, id: &ContainerID, ans: &mut Vec<ContainerID>) {
1174        let idx = self.arena.register_container(id);
1175        let Some(value) = self.store.get_value(idx) else {
1176            return;
1177        };
1178
1179        match value {
1180            LoroValue::Container(_) => unreachable!(),
1181            LoroValue::List(list) => {
1182                if idx.get_type() == ContainerType::Tree {
1183                    // Each tree node has an associated map container to represent
1184                    // the metadata of this node. When the user get the deep value,
1185                    // we need to add a field named `meta` to the tree node,
1186                    // whose value is deep value of map container.
1187                    let mut list = list.unwrap();
1188                    while let Some(node) = list.pop() {
1189                        let map = node.as_map().unwrap();
1190                        let meta = map.get("meta").unwrap();
1191                        let id = meta.as_container().unwrap();
1192                        ans.push(id.clone());
1193                        let children = map.get("children").unwrap();
1194                        let children = children.as_list().unwrap();
1195                        for child in children.iter() {
1196                            list.push(child.clone());
1197                        }
1198                    }
1199                } else {
1200                    for item in list.iter() {
1201                        if let LoroValue::Container(id) = item {
1202                            ans.push(id.clone());
1203                        }
1204                    }
1205                }
1206            }
1207            LoroValue::Map(map) => {
1208                for (_key, value) in map.iter() {
1209                    if let LoroValue::Container(id) = value {
1210                        ans.push(id.clone());
1211                    }
1212                }
1213            }
1214            _ => {}
1215        }
1216    }
1217
1218    // Because we need to calculate path based on [DocState], so we cannot extract
1219    // the event recorder to a separate module.
1220    fn diffs_to_event(&mut self, diffs: Vec<InternalDocDiff<'_>>, from: Frontiers) -> DocDiff {
1221        if diffs.is_empty() {
1222            panic!("diffs is empty");
1223        }
1224
1225        let triggered_by = diffs[0].by;
1226        debug_assert!(diffs.iter().all(|x| x.by == triggered_by));
1227        let mut containers = FxHashMap::default();
1228        let to = (*diffs.last().unwrap().new_version).to_owned();
1229        let origin = diffs[0].origin.clone();
1230        for diff in diffs {
1231            #[allow(clippy::unnecessary_to_owned)]
1232            for container_diff in diff.diff.into_owned() {
1233                if container_diff.is_container_deleted {
1234                    // omit event form deleted container
1235                    continue;
1236                }
1237                let Some((last_container_diff, _)) = containers.get_mut(&container_diff.idx) else {
1238                    if let Some(path) = self.get_path(container_diff.idx) {
1239                        containers.insert(container_diff.idx, (container_diff.diff, path));
1240                    } else {
1241                        // if we cannot find the path to the container, the container must be overwritten afterwards.
1242                        // So we can ignore the diff from it.
1243                        tracing::warn!(
1244                            "⚠️ WARNING: ignore event because cannot find its path {:#?} container id:{}",
1245                            &container_diff,
1246                            self.arena.idx_to_id(container_diff.idx).unwrap()
1247                        );
1248                    }
1249
1250                    continue;
1251                };
1252                // TODO: PERF avoid this clone
1253                *last_container_diff = last_container_diff
1254                    .clone()
1255                    .compose(container_diff.diff)
1256                    .unwrap();
1257            }
1258        }
1259        let mut diff: Vec<_> = containers
1260            .into_iter()
1261            .map(|(container, (diff, path))| {
1262                let idx = container;
1263                let id = self.arena.get_container_id(idx).unwrap();
1264                let is_unknown = id.is_unknown();
1265
1266                ContainerDiff {
1267                    id,
1268                    idx,
1269                    diff: diff.into_external().unwrap(),
1270                    is_unknown,
1271                    path,
1272                }
1273            })
1274            .collect();
1275
1276        // Sort by path length, so caller can apply the diff from the root to the leaf.
1277        // Otherwise, the caller may use a wrong path to apply the diff.
1278
1279        diff.sort_by_key(|x| {
1280            (
1281                x.path.len(),
1282                match &x.id {
1283                    ContainerID::Root { .. } => 0,
1284                    ContainerID::Normal { counter, .. } => *counter + 1,
1285                },
1286            )
1287        });
1288        DocDiff {
1289            from,
1290            to,
1291            origin,
1292            by: triggered_by,
1293            diff,
1294        }
1295    }
1296
1297    pub(crate) fn get_reachable(&mut self, id: &ContainerID) -> bool {
1298        if matches!(id, ContainerID::Root { .. }) {
1299            return true;
1300        }
1301
1302        let Some(mut idx) = self.arena.id_to_idx(id) else {
1303            return false;
1304        };
1305        loop {
1306            let id = self.arena.idx_to_id(idx).unwrap();
1307            if let Some(parent_idx) = self.arena.get_parent(idx) {
1308                let Some(parent_state) = self.store.get_container_mut(parent_idx) else {
1309                    return false;
1310                };
1311                if !parent_state.contains_child(&id) {
1312                    return false;
1313                }
1314                idx = parent_idx;
1315            } else {
1316                if id.is_root() {
1317                    return true;
1318                }
1319
1320                return false;
1321            }
1322        }
1323    }
1324
1325    // the container may be override, so it may return None
1326    pub(super) fn get_path(&mut self, idx: ContainerIdx) -> Option<Vec<(ContainerID, Index)>> {
1327        let mut ans = Vec::new();
1328        let mut idx = idx;
1329        loop {
1330            let id = self.arena.idx_to_id(idx).unwrap();
1331            if let Some(parent_idx) = self.arena.get_parent(idx) {
1332                let parent_state = self.store.get_container_mut(parent_idx)?;
1333                let Some(prop) = parent_state.get_child_index(&id) else {
1334                    tracing::info!("Missing in parent children");
1335                    return None;
1336                };
1337                ans.push((id, prop));
1338                idx = parent_idx;
1339            } else {
1340                // this container may be deleted
1341                let Ok(prop) = id.clone().into_root() else {
1342                    let id = format!("{}", &id);
1343                    tracing::info!(?id, "Missing parent - container is deleted");
1344                    return None;
1345                };
1346                ans.push((id, Index::Key(prop.0)));
1347                break;
1348            }
1349        }
1350
1351        ans.reverse();
1352
1353        Some(ans)
1354    }
1355
1356    pub(crate) fn check_before_decode_snapshot(&self) -> LoroResult<()> {
1357        if self.is_in_txn() {
1358            return Err(LoroError::DecodeError(
1359                "State is in txn".to_string().into_boxed_str(),
1360            ));
1361        }
1362
1363        if !self.can_import_snapshot() {
1364            return Err(LoroError::DecodeError(
1365                "State is not empty, cannot import snapshot directly"
1366                    .to_string()
1367                    .into_boxed_str(),
1368            ));
1369        }
1370
1371        Ok(())
1372    }
1373
1374    /// Check whether two [DocState]s are the same. Panic if not.
1375    ///
1376    /// Compared to check equality on `get_deep_value`, this function also checks the equality on richtext
1377    /// styles and states that are not reachable from the root.
1378    ///
1379    /// This is only used for test.
1380    pub(crate) fn check_is_the_same(&mut self, other: &mut Self) {
1381        fn get_entries_for_state(
1382            arena: &SharedArena,
1383            state: &mut State,
1384        ) -> Option<(ContainerID, (ContainerIdx, LoroValue))> {
1385            if state.is_state_empty() {
1386                return None;
1387            }
1388
1389            let id = arena.idx_to_id(state.container_idx()).unwrap();
1390            let value = match state {
1391                State::RichtextState(s) => s.get_richtext_value(),
1392                _ => state.get_value(),
1393            };
1394            if match &value {
1395                LoroValue::List(l) => l.is_empty(),
1396                LoroValue::Map(m) => m.is_empty(),
1397                _ => false,
1398            } {
1399                return None;
1400            }
1401            #[cfg(feature = "counter")]
1402            if id.container_type() == ContainerType::Counter {
1403                if let LoroValue::Double(c) = value {
1404                    if c.abs() < f64::EPSILON {
1405                        return None;
1406                    }
1407                }
1408            }
1409
1410            Some((id, (state.container_idx(), value)))
1411        }
1412
1413        let self_id_to_states: FxHashMap<ContainerID, (ContainerIdx, LoroValue)> = self
1414            .store
1415            .iter_and_decode_all()
1416            .filter_map(|state: &mut State| {
1417                let arena = &self.arena;
1418                get_entries_for_state(arena, state)
1419            })
1420            .collect();
1421        let mut other_id_to_states: FxHashMap<ContainerID, (ContainerIdx, LoroValue)> = other
1422            .store
1423            .iter_and_decode_all()
1424            .filter_map(|state: &mut State| {
1425                let arena = &other.arena;
1426                get_entries_for_state(arena, state)
1427            })
1428            .collect();
1429        for (id, (idx, this_value)) in self_id_to_states {
1430            let (_, other_value) = match other_id_to_states.remove(&id) {
1431                Some(x) => x,
1432                None => {
1433                    panic!(
1434                        "id: {:?}, path: {:?} is missing, value={:?}",
1435                        id,
1436                        self.get_path(idx),
1437                        &this_value
1438                    );
1439                }
1440            };
1441
1442            pretty_assertions::assert_eq!(
1443                this_value,
1444                other_value,
1445                "[self!=other] id: {:?}, path: {:?}",
1446                id,
1447                self.get_path(idx)
1448            );
1449        }
1450
1451        if !other_id_to_states.is_empty() {
1452            panic!("other has more states {:#?}", &other_id_to_states);
1453        }
1454    }
1455
1456    pub fn log_estimated_size(&self) {
1457        let state_entries_size =
1458            self.store.len() * (std::mem::size_of::<State>() + std::mem::size_of::<ContainerIdx>());
1459        let mut state_size_sum = 0;
1460        state_size_sum += self.store.estimate_size();
1461
1462        eprintln!(
1463            "ContainerNum: {}\nEstimated state size: \nEntries: {} \nSum: {}",
1464            self.store.len(),
1465            state_entries_size,
1466            state_size_sum
1467        );
1468    }
1469
1470    pub fn create_state(&self, idx: ContainerIdx) -> State {
1471        let config = &self.config;
1472        let peer = self.peer.load(std::sync::atomic::Ordering::Relaxed);
1473        create_state_(idx, config, peer)
1474    }
1475
1476    pub fn create_unknown_state(&self, idx: ContainerIdx) -> State {
1477        State::UnknownState(UnknownState::new(idx))
1478    }
1479
1480    pub fn get_relative_position(&mut self, pos: &Cursor, use_event_index: bool) -> Option<usize> {
1481        let idx = self.arena.register_container(&pos.container);
1482        let state = self.store.get_container_mut(idx)?;
1483        if let Some(id) = pos.id {
1484            match state {
1485                State::ListState(s) => s.get_index_of_id(id),
1486                State::RichtextState(s) => s.get_text_index_of_id(id, use_event_index),
1487                State::MovableListState(s) => s.get_index_of_id(id),
1488                State::MapState(_) | State::TreeState(_) | State::UnknownState(_) => unreachable!(),
1489                #[cfg(feature = "counter")]
1490                State::CounterState(_) => unreachable!(),
1491            }
1492        } else {
1493            if matches!(pos.side, crate::cursor::Side::Left) {
1494                return Some(0);
1495            }
1496
1497            match state {
1498                State::ListState(s) => Some(s.len()),
1499                State::RichtextState(s) => Some(if use_event_index {
1500                    s.len_event()
1501                } else {
1502                    s.len_unicode()
1503                }),
1504                State::MovableListState(s) => Some(s.len()),
1505                State::MapState(_) | State::TreeState(_) | State::UnknownState(_) => unreachable!(),
1506                #[cfg(feature = "counter")]
1507                State::CounterState(_) => unreachable!(),
1508            }
1509        }
1510    }
1511
1512    pub fn get_value_by_path(&mut self, path: &[Index]) -> Option<LoroValue> {
1513        if path.is_empty() {
1514            return None;
1515        }
1516
1517        enum CurContainer {
1518            Container(ContainerIdx),
1519            TreeNode {
1520                tree: ContainerIdx,
1521                node: Option<TreeID>,
1522            },
1523        }
1524
1525        let mut state_idx = {
1526            let root_index = path[0].as_key()?;
1527            CurContainer::Container(self.arena.get_root_container_idx_by_key(root_index)?)
1528        };
1529
1530        if path.len() == 1 {
1531            if let CurContainer::Container(c) = state_idx {
1532                let cid = self.arena.idx_to_id(c)?;
1533                return Some(LoroValue::Container(cid));
1534            }
1535        }
1536
1537        let mut i = 1;
1538        while i < path.len() - 1 {
1539            let index = &path[i];
1540            match state_idx {
1541                CurContainer::Container(idx) => {
1542                    let parent_state = self.store.get_container_mut(idx)?;
1543                    match parent_state {
1544                        State::ListState(l) => {
1545                            let Some(LoroValue::Container(c)) = l.get(*index.as_seq()?) else {
1546                                return None;
1547                            };
1548                            state_idx = CurContainer::Container(self.arena.register_container(c));
1549                        }
1550                        State::MovableListState(l) => {
1551                            let Some(LoroValue::Container(c)) =
1552                                l.get(*index.as_seq()?, IndexType::ForUser)
1553                            else {
1554                                return None;
1555                            };
1556                            state_idx = CurContainer::Container(self.arena.register_container(c));
1557                        }
1558                        State::MapState(m) => {
1559                            let Some(LoroValue::Container(c)) = m.get(index.as_key()?) else {
1560                                return None;
1561                            };
1562                            state_idx = CurContainer::Container(self.arena.register_container(c));
1563                        }
1564                        State::RichtextState(_) => return None,
1565                        State::TreeState(_) => {
1566                            state_idx = CurContainer::TreeNode {
1567                                tree: idx,
1568                                node: None,
1569                            };
1570                            continue;
1571                        }
1572                        #[cfg(feature = "counter")]
1573                        State::CounterState(_) => return None,
1574                        State::UnknownState(_) => unreachable!(),
1575                    }
1576                }
1577                CurContainer::TreeNode { tree, node } => match index {
1578                    Index::Key(internal_string) => {
1579                        let node = node?;
1580                        let idx = self
1581                            .arena
1582                            .register_container(&node.associated_meta_container());
1583                        let map = self.store.get_container(idx)?;
1584                        let Some(LoroValue::Container(c)) =
1585                            map.as_map_state().unwrap().get(internal_string)
1586                        else {
1587                            return None;
1588                        };
1589
1590                        state_idx = CurContainer::Container(self.arena.register_container(c));
1591                    }
1592                    Index::Seq(i) => {
1593                        let tree_state =
1594                            self.store.get_container_mut(tree)?.as_tree_state().unwrap();
1595                        let parent: TreeParentId = if let Some(node) = node {
1596                            node.into()
1597                        } else {
1598                            TreeParentId::Root
1599                        };
1600                        let child = tree_state.get_children(&parent)?.nth(*i)?;
1601                        state_idx = CurContainer::TreeNode {
1602                            tree,
1603                            node: Some(child),
1604                        };
1605                    }
1606                    Index::Node(tree_id) => {
1607                        let tree_state =
1608                            self.store.get_container_mut(tree)?.as_tree_state().unwrap();
1609                        if tree_state.parent(tree_id).is_some() {
1610                            state_idx = CurContainer::TreeNode {
1611                                tree,
1612                                node: Some(*tree_id),
1613                            }
1614                        } else {
1615                            return None;
1616                        }
1617                    }
1618                },
1619            }
1620            i += 1;
1621        }
1622
1623        let parent_idx = match state_idx {
1624            CurContainer::Container(container_idx) => container_idx,
1625            CurContainer::TreeNode { tree, node } => {
1626                if let Some(node) = node {
1627                    self.arena
1628                        .register_container(&node.associated_meta_container())
1629                } else {
1630                    tree
1631                }
1632            }
1633        };
1634
1635        let parent_state = self.store.get_or_create_mut(parent_idx);
1636        let index = path.last().unwrap();
1637        let value: LoroValue = match parent_state {
1638            State::ListState(l) => l.get(*index.as_seq()?).cloned()?,
1639            State::MovableListState(l) => l.get(*index.as_seq()?, IndexType::ForUser).cloned()?,
1640            State::MapState(m) => {
1641                if let Some(key) = index.as_key() {
1642                    m.get(key).cloned()?
1643                } else if let CurContainer::TreeNode { tree, node } = state_idx {
1644                    match index {
1645                        Index::Seq(index) => {
1646                            let tree_state =
1647                                self.store.get_container_mut(tree)?.as_tree_state().unwrap();
1648                            let parent: TreeParentId = if let Some(node) = node {
1649                                node.into()
1650                            } else {
1651                                TreeParentId::Root
1652                            };
1653                            let child = tree_state.get_children(&parent)?.nth(*index)?;
1654                            child.associated_meta_container().into()
1655                        }
1656                        Index::Node(id) => id.associated_meta_container().into(),
1657                        _ => return None,
1658                    }
1659                } else {
1660                    return None;
1661                }
1662            }
1663            State::RichtextState(s) => {
1664                let s = s.to_string_mut();
1665                s.chars()
1666                    .nth(*index.as_seq()?)
1667                    .map(|c| c.to_string().into())?
1668            }
1669            State::TreeState(_) => {
1670                let id = index.as_node()?;
1671                let cid = id.associated_meta_container();
1672                cid.into()
1673            }
1674            #[cfg(feature = "counter")]
1675            State::CounterState(_) => unreachable!(),
1676            State::UnknownState(_) => unreachable!(),
1677        };
1678
1679        Some(value)
1680    }
1681
1682    pub(crate) fn shallow_root_store(&self) -> Option<&Arc<GcStore>> {
1683        self.store.shallow_root_store()
1684    }
1685}
1686
1687fn create_state_(idx: ContainerIdx, config: &Configure, peer: u64) -> State {
1688    match idx.get_type() {
1689        ContainerType::Map => State::MapState(Box::new(MapState::new(idx))),
1690        ContainerType::List => State::ListState(Box::new(ListState::new(idx))),
1691        ContainerType::Text => State::RichtextState(Box::new(RichtextState::new(
1692            idx,
1693            config.text_style_config.clone(),
1694        ))),
1695        ContainerType::Tree => State::TreeState(Box::new(TreeState::new(idx, peer))),
1696        ContainerType::MovableList => State::MovableListState(Box::new(MovableListState::new(idx))),
1697        #[cfg(feature = "counter")]
1698        ContainerType::Counter => {
1699            State::CounterState(Box::new(counter_state::CounterState::new(idx)))
1700        }
1701        ContainerType::Unknown(_) => State::UnknownState(UnknownState::new(idx)),
1702    }
1703}
1704
1705fn trigger_on_new_container(
1706    state_diff: &Diff,
1707    mut listener: impl FnMut(ContainerIdx),
1708    arena: &SharedArena,
1709) {
1710    match state_diff {
1711        Diff::List(list) => {
1712            for delta in list.iter() {
1713                if let DeltaItem::Replace {
1714                    value,
1715                    attr,
1716                    delete: _,
1717                } = delta
1718                {
1719                    if attr.from_move {
1720                        continue;
1721                    }
1722
1723                    for v in value.iter() {
1724                        if let ValueOrHandler::Handler(h) = v {
1725                            let idx = h.container_idx();
1726                            listener(idx);
1727                        }
1728                    }
1729                }
1730            }
1731        }
1732        Diff::Map(map) => {
1733            for (_, v) in map.updated.iter() {
1734                if let Some(ValueOrHandler::Handler(h)) = &v.value {
1735                    let idx = h.container_idx();
1736                    listener(idx);
1737                }
1738            }
1739        }
1740        Diff::Tree(tree) => {
1741            for item in tree.iter() {
1742                if matches!(item.action, TreeExternalDiff::Create { .. }) {
1743                    let id = item.target.associated_meta_container();
1744                    listener(arena.id_to_idx(&id).unwrap());
1745                }
1746            }
1747        }
1748        _ => {}
1749    };
1750}
1751
1752#[derive(Default, Clone)]
1753struct EventRecorder {
1754    recording_diff: bool,
1755    // A batch of diffs will be converted to a event when
1756    // they cannot be merged with the next diff.
1757    diffs: Vec<InternalDocDiff<'static>>,
1758    events: Vec<DocDiff>,
1759    diff_start_version: Option<Frontiers>,
1760}
1761
1762impl EventRecorder {
1763    #[allow(unused)]
1764    pub fn new() -> Self {
1765        Self::default()
1766    }
1767}
1768
1769#[test]
1770fn test_size() {
1771    println!("Size of State = {}", std::mem::size_of::<State>());
1772    println!("Size of MapState = {}", std::mem::size_of::<MapState>());
1773    println!("Size of ListState = {}", std::mem::size_of::<ListState>());
1774    println!(
1775        "Size of TextState = {}",
1776        std::mem::size_of::<RichtextState>()
1777    );
1778    println!("Size of TreeState = {}", std::mem::size_of::<TreeState>());
1779}