Skip to main content

loro_internal/
state.rs

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