Skip to main content

yrs/
doc.rs

1use crate::block::{ClientID, ItemContent, ItemPtr, Prelim};
2use crate::branch::BranchPtr;
3use crate::encoding::read::Error;
4use crate::event::{SubdocsEvent, TransactionCleanupEvent, UpdateEvent};
5use crate::store::{DocStore, StoreInner};
6use crate::transaction::{Origin, TransactionMut};
7use crate::types::{RootRef, ToJson};
8use crate::updates::decoder::{Decode, Decoder};
9use crate::updates::encoder::{Encode, Encoder};
10use crate::utils::OptionExt;
11use crate::{
12    uuid_v4, uuid_v4_from, ArrayRef, BranchID, MapRef, Out, ReadTxn, TextRef, Transact,
13    TransactionAcqError, Uuid, WriteTxn, XmlFragmentRef,
14};
15use crate::{Any, Subscription};
16use std::collections::HashMap;
17use std::convert::TryFrom;
18use std::fmt::Formatter;
19use std::sync::Arc;
20
21/// A Yrs document type. Documents are the most important units of collaborative resources management.
22/// All shared collections live within a scope of their corresponding documents. All updates are
23/// generated on per-document basis (rather than individual shared type). All operations on shared
24/// collections happen via [Transaction](crate::Transaction), which lifetime is also bound to a document.
25///
26/// Document manages so-called root types, which are top-level shared types definitions (as opposed
27/// to recursively nested types).
28///
29/// # Example
30///
31/// ```rust
32/// use yrs::{Doc, ReadTxn, StateVector, Text, Transact, Update};
33/// use yrs::updates::decoder::Decode;
34/// use yrs::updates::encoder::Encode;
35///
36/// let doc = Doc::new();
37/// let root = doc.get_or_insert_text("root-type-name");
38/// let mut txn = doc.transact_mut(); // all Yrs operations happen in scope of a transaction
39/// root.push(&mut txn, "hello world"); // append text to our collaborative document
40///
41/// // in order to exchange data with other documents we first need to create a state vector
42/// let remote_doc = Doc::new();
43/// let mut remote_txn = remote_doc.transact_mut();
44/// let state_vector = remote_txn.state_vector().encode_v1();
45///
46/// // now compute a differential update based on remote document's state vector
47/// let update = txn.encode_diff_v1(&StateVector::decode_v1(&state_vector).unwrap());
48///
49/// // both update and state vector are serializable, we can pass the over the wire
50/// // now apply update to a remote document
51/// remote_txn.apply_update(Update::decode_v1(update.as_slice()).unwrap());
52/// ```
53#[repr(transparent)]
54#[derive(Debug, Clone)]
55pub struct Doc {
56    pub(crate) store: DocStore,
57}
58
59unsafe impl Send for Doc {}
60unsafe impl Sync for Doc {}
61
62impl TryFrom<Out> for Doc {
63    type Error = Out;
64
65    fn try_from(value: Out) -> Result<Self, Self::Error> {
66        match value {
67            Out::YDoc(value) => Ok(value),
68            other => Err(other),
69        }
70    }
71}
72
73/// Generates `observe_*`, `observe_*_with`, and `unobserve_*` methods on [`Doc`] for a given
74/// event. Each event group produces 5 method definitions: sync and non-sync variants of `observe`
75/// and `observe_with`, plus a single `unobserve`.
76macro_rules! define_doc_observer {
77    (
78        $(#[doc = $doc:literal])*
79        $observe:ident, $observe_with:ident, $unobserve:ident,
80        $field:ident, $($bound:tt)+
81    ) => {
82        $(#[doc = $doc])*
83        #[cfg(feature = "sync")]
84        pub fn $observe<F>(&self, f: F) -> Result<Subscription, TransactionAcqError>
85        where
86            F: $($bound)+ + Send + Sync + 'static,
87        {
88            let mut store = self
89                .store
90                .try_write()
91                .ok_or(TransactionAcqError::ExclusiveAcqFailed)?;
92            let events = store.events.get_or_init();
93            Ok(events.$field.subscribe(Box::new(f)))
94        }
95
96        $(#[doc = $doc])*
97        #[cfg(not(feature = "sync"))]
98        pub fn $observe<F>(&self, f: F) -> Result<Subscription, TransactionAcqError>
99        where
100            F: $($bound)+ + 'static,
101        {
102            let mut store = self
103                .store
104                .try_write()
105                .ok_or(TransactionAcqError::ExclusiveAcqFailed)?;
106            let events = store.events.get_or_init();
107            Ok(events.$field.subscribe(Box::new(f)))
108        }
109
110        #[cfg(feature = "sync")]
111        pub fn $observe_with<K, F>(&self, key: K, f: F) -> Result<(), TransactionAcqError>
112        where
113            K: Into<Origin>,
114            F: $($bound)+ + Send + Sync + 'static,
115        {
116            let mut store = self
117                .store
118                .try_write()
119                .ok_or(TransactionAcqError::ExclusiveAcqFailed)?;
120            let events = store.events.get_or_init();
121            events.$field.subscribe_with(key.into(), Box::new(f));
122            Ok(())
123        }
124
125        #[cfg(not(feature = "sync"))]
126        pub fn $observe_with<K, F>(&self, key: K, f: F) -> Result<(), TransactionAcqError>
127        where
128            K: Into<Origin>,
129            F: $($bound)+ + 'static,
130        {
131            let mut store = self
132                .store
133                .try_write()
134                .ok_or(TransactionAcqError::ExclusiveAcqFailed)?;
135            let events = store.events.get_or_init();
136            events.$field.subscribe_with(key.into(), Box::new(f));
137            Ok(())
138        }
139
140        pub fn $unobserve<K>(&self, key: K) -> Result<bool, TransactionAcqError>
141        where
142            K: Into<Origin>,
143        {
144            let mut store = self
145                .store
146                .try_write()
147                .ok_or(TransactionAcqError::ExclusiveAcqFailed)?;
148            let events = store.events.get_or_init();
149            Ok(events.$field.unsubscribe(&key.into()))
150        }
151    };
152}
153
154impl Doc {
155    /// Creates a new document with a randomized client identifier.
156    pub fn new() -> Self {
157        Self::with_options(Options::default())
158    }
159
160    #[doc(hidden)]
161    pub fn into_raw(self) -> *const Doc {
162        let ptr = Arc::into_raw(self.store.0);
163        ptr as *const Doc
164    }
165
166    #[doc(hidden)]
167    pub unsafe fn from_raw(ptr: *const Doc) -> Doc {
168        let ptr = ptr as *const StoreInner;
169        let cell = Arc::from_raw(ptr);
170        Doc {
171            store: DocStore(cell),
172        }
173    }
174
175    #[doc(hidden)]
176    pub fn as_raw(self) -> *const Doc {
177        let ptr = Arc::as_ptr(&self.store.0);
178        ptr as *const Doc
179    }
180
181    /// Creates a new document with a specified `client_id`. It's up to a caller to guarantee that
182    /// this identifier is unique across all communicating replicas of that document.
183    pub fn with_client_id(client_id: u64) -> Self {
184        Self::with_options(Options::with_client_id(ClientID::new(client_id)))
185    }
186
187    /// Creates a new document with a configured set of [Options].
188    pub fn with_options(options: Options) -> Self {
189        Doc {
190            store: DocStore::new(options, None),
191        }
192    }
193
194    pub(crate) fn subdoc(parent: ItemPtr, options: Options) -> Self {
195        Doc {
196            store: DocStore::new(options, Some(parent)),
197        }
198    }
199
200    pub(crate) fn store(&self) -> &DocStore {
201        &self.store
202    }
203
204    /// A unique client identifier, that's also a unique identifier of current document replica
205    /// and it's subdocuments.
206    ///
207    /// Default: randomly generated.
208    pub fn client_id(&self) -> ClientID {
209        self.store.options().client_id
210    }
211
212    /// A globally unique identifier, that's also a unique identifier of current document replica,
213    /// and unlike [Doc::client_id] it's not shared with its subdocuments.
214    ///
215    /// Default: randomly generated UUID v4.
216    pub fn guid(&self) -> Uuid {
217        self.store.options().guid.clone()
218    }
219
220    /// Returns a unique collection identifier, if defined.
221    ///
222    /// Default: `None`.
223    pub fn collection_id(&self) -> Option<Arc<str>> {
224        self.store.options().collection_id.clone()
225    }
226
227    /// Informs if current document is skipping garbage collection on deleted collections
228    /// on transaction commit.
229    ///
230    /// Default: `false`.
231    pub fn skip_gc(&self) -> bool {
232        self.store.options().skip_gc
233    }
234
235    /// If current document is subdocument, it will automatically for a document to load.
236    ///
237    /// Default: `false`.
238    pub fn auto_load(&self) -> bool {
239        self.store.options().auto_load
240    }
241
242    /// Whether the document should be synced by the provider now.
243    /// This is toggled to true when you call [Doc::load]
244    ///
245    /// Default value: `true`.
246    pub fn should_load(&self) -> bool {
247        self.store.options().should_load
248    }
249
250    /// Returns encoding used to count offsets and lengths in text operations.
251    pub fn offset_kind(&self) -> OffsetKind {
252        self.store.options().offset_kind
253    }
254
255    /// Returns a [TextRef] data structure stored under a given `name`. Text structures are used for
256    /// collaborative text editing: they expose operations to append and remove chunks of text,
257    /// which are free to execute concurrently by multiple peers over remote boundaries.
258    ///
259    /// If no structure under defined `name` existed before, it will be created and returned
260    /// instead.
261    ///
262    /// If a structure under defined `name` already existed, but its type was different it will be
263    /// reinterpreted as a text (in such case a sequence component of complex data type will be
264    /// interpreted as a list of text chunks).
265    ///
266    /// # Panics
267    ///
268    /// This method requires exclusive access to an underlying document store. If there
269    /// is another transaction in process, it will panic. It's advised to define all root shared
270    /// types during the document creation.
271    pub fn get_or_insert_text<N: Into<Arc<str>>>(&self, name: N) -> TextRef {
272        TextRef::root(name).get_or_create(&mut self.transact_mut())
273    }
274
275    /// Returns a [MapRef] data structure stored under a given `name`. Maps are used to store key-value
276    /// pairs associated. These values can be primitive data (similar but not limited to
277    /// a JavaScript Object Notation) as well as other shared types (Yrs maps, arrays, text
278    /// structures etc.), enabling to construct a complex recursive tree structures.
279    ///
280    /// If no structure under defined `name` existed before, it will be created and returned
281    /// instead.
282    ///
283    /// If a structure under defined `name` already existed, but its type was different it will be
284    /// reinterpreted as a map (in such case a map component of complex data type will be
285    /// interpreted as native map).
286    ///
287    /// # Panics
288    ///
289    /// This method requires exclusive access to an underlying document store. If there
290    /// is another transaction in process, it will panic. It's advised to define all root shared
291    /// types during the document creation.
292    pub fn get_or_insert_map<N: Into<Arc<str>>>(&self, name: N) -> MapRef {
293        MapRef::root(name).get_or_create(&mut self.transact_mut())
294    }
295
296    /// Returns an [ArrayRef] data structure stored under a given `name`. Array structures are used for
297    /// storing a sequences of elements in ordered manner, positioning given element accordingly
298    /// to its index.
299    ///
300    /// If no structure under defined `name` existed before, it will be created and returned
301    /// instead.
302    ///
303    /// If a structure under defined `name` already existed, but its type was different it will be
304    /// reinterpreted as an array (in such case a sequence component of complex data type will be
305    /// interpreted as a list of inserted values).
306    ///
307    /// # Panics
308    ///
309    /// This method requires exclusive access to an underlying document store. If there
310    /// is another transaction in process, it will panic. It's advised to define all root shared
311    /// types during the document creation.
312    pub fn get_or_insert_array<N: Into<Arc<str>>>(&self, name: N) -> ArrayRef {
313        ArrayRef::root(name).get_or_create(&mut self.transact_mut())
314    }
315
316    /// Returns a [XmlFragmentRef] data structure stored under a given `name`. XML elements represent
317    /// nodes of XML document. They can contain attributes (key-value pairs, both of string type)
318    /// and other nested XML elements or text values, which are stored in their insertion
319    /// order.
320    ///
321    /// If no structure under defined `name` existed before, it will be created and returned
322    /// instead.
323    ///
324    /// If a structure under defined `name` already existed, but its type was different it will be
325    /// reinterpreted as a XML element (in such case a map component of complex data type will be
326    /// interpreted as map of its attributes, while a sequence component - as a list of its child
327    /// XML nodes).
328    ///
329    /// # Panics
330    ///
331    /// This method requires exclusive access to an underlying document store. If there
332    /// is another transaction in process, it will panic. It's advised to define all root shared
333    /// types during the document creation.
334    pub fn get_or_insert_xml_fragment<N: Into<Arc<str>>>(&self, name: N) -> XmlFragmentRef {
335        XmlFragmentRef::root(name).get_or_create(&mut self.transact_mut())
336    }
337
338    define_doc_observer!(
339        /// Subscribe callback function for any changes performed within transaction scope. These
340        /// changes are encoded using lib0 v1 encoding and can be decoded using [Update::decode_v1]
341        /// if necessary or passed to remote peers right away. This callback is triggered on
342        /// function commit.
343        observe_update_v1, observe_update_v1_with, unobserve_update_v1,
344        update_v1_events, FnMut(&TransactionMut, &UpdateEvent)
345    );
346
347    define_doc_observer!(
348        /// Subscribe callback function for any changes performed within transaction scope. These
349        /// changes are encoded using lib0 v2 encoding and can be decoded using [Update::decode_v2]
350        /// if necessary or passed to remote peers right away. This callback is triggered on
351        /// function commit.
352        observe_update_v2, observe_update_v2_with, unobserve_update_v2,
353        update_v2_events, FnMut(&TransactionMut, &UpdateEvent)
354    );
355
356    define_doc_observer!(
357        /// Subscribe callback function to updates on the `Doc`. The callback will receive state
358        /// updates and deletions when a document transaction is committed.
359        observe_transaction_cleanup, observe_transaction_cleanup_with, unobserve_transaction_cleanup,
360        transaction_cleanup_events, FnMut(&TransactionMut, &TransactionCleanupEvent)
361    );
362
363    define_doc_observer!(
364        observe_after_transaction,
365        observe_after_transaction_with,
366        unobserve_after_transaction,
367        after_transaction_events,
368        FnMut(&mut TransactionMut)
369    );
370
371    define_doc_observer!(
372        /// Subscribe a callback that fires after the transaction body completes but before
373        /// type-level observers are triggered. This is used by attribution managers to update
374        /// their internal state before any observer reads attribution data.
375        observe_before_observer_calls, observe_before_observer_calls_with, unobserve_before_observer_calls,
376        before_observer_calls_events, FnMut(&TransactionMut)
377    );
378
379    define_doc_observer!(
380        /// Subscribe callback function, that will be called whenever a subdocuments inserted in
381        /// this [Doc] will request a load.
382        observe_subdocs, observe_subdocs_with, unobserve_subdocs,
383        subdocs_events, FnMut(&TransactionMut, &SubdocsEvent)
384    );
385
386    define_doc_observer!(
387        /// Subscribe callback function, that will be called whenever a [Doc::destroy] has been
388        /// called.
389        observe_destroy, observe_destroy_with, unobserve_destroy,
390        destroy_events, FnMut(&TransactionMut, &Doc)
391    );
392
393    /// Sends a load request to a parent document. Works only if current document is a sub-document
394    /// of a document.
395    pub fn load<T>(&self, parent_txn: &mut T)
396    where
397        T: WriteTxn,
398    {
399        let should_load = self.store.set_should_load(true);
400        if !should_load {
401            let txn = self.transact();
402            if txn.store().is_subdoc() {
403                parent_txn
404                    .subdocs_mut()
405                    .loaded
406                    .insert(self.addr(), self.clone());
407            }
408        }
409    }
410
411    /// Starts destroy procedure for a current document, triggering an "destroy" callback and
412    /// invalidating all event callback subscriptions.
413    pub fn destroy(&self, parent_txn: Option<&mut TransactionMut<'_>>) {
414        let mut txn = self.transact_mut();
415        let store = txn.store_mut();
416        let subdocs: Vec<_> = store.subdocs.values().cloned().collect();
417        for subdoc in subdocs {
418            subdoc.destroy(Some(&mut txn));
419        }
420        if let Some(parent_txn) = parent_txn {
421            if let Some(mut item) = txn.store.parent.take() {
422                let parent_ref = item.clone();
423                let is_deleted = item.is_deleted();
424                if let ItemContent::Doc(_, content) = &mut item.content {
425                    let mut options = (**content.store.options()).clone();
426                    options.should_load = false;
427                    let new_ref = Doc::subdoc(parent_ref, options);
428                    if !is_deleted {
429                        parent_txn
430                            .subdocs_mut()
431                            .added
432                            .insert(new_ref.addr(), new_ref.clone());
433                    }
434                    parent_txn
435                        .subdocs_mut()
436                        .removed
437                        .insert(new_ref.addr(), new_ref.clone());
438
439                    *content = new_ref;
440                }
441            }
442        }
443        // super.destroy(): cleanup the events
444        if let Some(mut events) = txn.store_mut().events.take() {
445            events.destroy_events.trigger(|cb| cb(&txn, self));
446        }
447    }
448
449    /// If current document has been inserted as a sub-document, returns a reference to a parent
450    /// document, which contains it.
451    pub fn parent_doc(&self) -> Option<Doc> {
452        let txn = self.transact();
453        txn.parent_doc()
454    }
455
456    pub fn branch_id(&self) -> Option<BranchID> {
457        let txn = self.transact();
458        txn.branch_id()
459    }
460
461    pub fn ptr_eq(a: &Doc, b: &Doc) -> bool {
462        Arc::ptr_eq(&a.store.0, &b.store.0)
463    }
464
465    pub(crate) fn addr(&self) -> DocAddr {
466        DocAddr::new(&self)
467    }
468}
469
470impl PartialEq for Doc {
471    fn eq(&self, other: &Self) -> bool {
472        self.guid() == other.guid()
473    }
474}
475
476impl std::fmt::Display for Doc {
477    fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
478        write!(f, "Doc(id: {}, guid: {})", self.client_id(), self.guid())
479    }
480}
481
482impl TryFrom<ItemPtr> for Doc {
483    type Error = ItemPtr;
484
485    fn try_from(item: ItemPtr) -> Result<Self, Self::Error> {
486        if let ItemContent::Doc(_, doc) = &item.content {
487            Ok(doc.clone())
488        } else {
489            Err(item)
490        }
491    }
492}
493
494impl Default for Doc {
495    fn default() -> Self {
496        Doc::new()
497    }
498}
499
500impl ToJson for Doc {
501    fn to_json<T: ReadTxn>(&self, txn: &T) -> Any {
502        let mut m = HashMap::new();
503        for (key, value) in txn.root_refs() {
504            m.insert(key.to_string(), value.to_json(txn));
505        }
506        Any::from(m)
507    }
508}
509
510/// Configuration options of [Doc] instance.
511#[derive(Debug, Clone, PartialEq, Eq)]
512pub struct Options {
513    /// Globally unique client identifier. This value must be unique across all active collaborating
514    /// peers, otherwise a update collisions will happen, causing document store state to be corrupted.
515    ///
516    /// Default value: randomly generated.
517    pub client_id: ClientID,
518    /// A globally unique identifier for this document.
519    ///
520    /// Default value: randomly generated UUID v4.
521    pub guid: Uuid,
522    /// Associate this document with a collection. This only plays a role if your provider has
523    /// a concept of collection.
524    ///
525    /// Default value: `None`.
526    pub collection_id: Option<Arc<str>>,
527    /// How to we count offsets and lengths used in text operations.
528    ///
529    /// Default value: [OffsetKind::Bytes].
530    pub offset_kind: OffsetKind,
531    /// Determines if transactions commits should try to perform GC-ing of deleted items.
532    ///
533    /// Default value: `false`.
534    pub skip_gc: bool,
535    /// If a subdocument, automatically load document. If this is a subdocument, remote peers will
536    /// load the document as well automatically.
537    ///
538    /// Default value: `false`.
539    pub auto_load: bool,
540    /// Whether the document should be synced by the provider now.
541    /// This is toggled to true when you call ydoc.load().
542    ///
543    /// Default value: `true`.
544    pub should_load: bool,
545
546    /// Whenever we receive an update that might remove piece of text, it might turn out that it was
547    /// surrounded by the formatting attributes, that now are effectively dead and unrenderable, but
548    /// still are considered alive blocks.
549    ///
550    /// This flag orders cleanup of dangling formatting attributes.
551    pub cleanup_formatting: bool,
552}
553
554impl Options {
555    pub fn with_client_id(client_id: ClientID) -> Self {
556        Options {
557            client_id,
558            guid: uuid_v4(),
559            collection_id: None,
560            offset_kind: OffsetKind::Bytes,
561            skip_gc: false,
562            auto_load: false,
563            should_load: true,
564            cleanup_formatting: true,
565        }
566    }
567
568    pub fn with_guid_and_client_id(guid: Uuid, client_id: ClientID) -> Self {
569        Options {
570            client_id,
571            guid,
572            collection_id: None,
573            offset_kind: OffsetKind::Bytes,
574            skip_gc: false,
575            auto_load: false,
576            should_load: true,
577            cleanup_formatting: false,
578        }
579    }
580
581    fn as_any(&self) -> Any {
582        let mut m = HashMap::new();
583        m.insert("gc".to_owned(), (!self.skip_gc).into());
584        if let Some(collection_id) = self.collection_id.as_ref() {
585            m.insert("collectionId".to_owned(), collection_id.clone().into());
586        }
587        let encoding = match self.offset_kind {
588            OffsetKind::Bytes => 1,
589            OffsetKind::Utf16 => 0, // 0 for compatibility with Yjs, which doesn't have this option
590        };
591        m.insert("encoding".to_owned(), Any::BigInt(encoding));
592        m.insert("autoLoad".to_owned(), self.auto_load.into());
593        m.insert("shouldLoad".to_owned(), self.should_load.into());
594        Any::from(m)
595    }
596}
597
598impl Default for Options {
599    fn default() -> Self {
600        let client_id = ClientID::random();
601        let mut rng = fastrand::Rng::new();
602        let uuid = uuid_v4_from(rng.u128(..));
603        Self::with_guid_and_client_id(uuid, client_id)
604    }
605}
606
607impl Encode for Options {
608    fn encode<E: Encoder>(&self, encoder: &mut E) {
609        let guid = self.guid.to_string();
610        encoder.write_string(&guid);
611        encoder.write_any(&self.as_any())
612    }
613}
614
615impl Decode for Options {
616    fn decode<D: Decoder>(decoder: &mut D) -> Result<Self, Error> {
617        let mut options = Options::default();
618        options.should_load = false; // for decoding shouldLoad is false by default
619        let guid = decoder.read_string()?;
620        options.guid = guid.into();
621
622        if let Any::Map(opts) = decoder.read_any()? {
623            for (k, v) in opts.iter() {
624                match (k.as_str(), v) {
625                    ("gc", Any::Bool(gc)) => options.skip_gc = !*gc,
626                    ("autoLoad", Any::Bool(auto_load)) => options.auto_load = *auto_load,
627                    ("collectionId", Any::String(cid)) => options.collection_id = Some(cid.clone()),
628                    ("encoding", Any::BigInt(1)) => options.offset_kind = OffsetKind::Bytes,
629                    ("encoding", _) => options.offset_kind = OffsetKind::Utf16,
630                    _ => { /* do nothing */ }
631                }
632            }
633        }
634
635        Ok(options)
636    }
637}
638
639/// Determines how string length and offsets of [Text]/[XmlText] are being determined.
640#[repr(u8)]
641#[derive(Debug, Clone, Copy, PartialEq, Eq)]
642pub enum OffsetKind {
643    /// Compute editable strings length and offset using UTF-8 byte count.
644    Bytes,
645    /// Compute editable strings length and offset using UTF-16 chars count.
646    Utf16,
647}
648
649impl Prelim for Doc {
650    type Return = Doc;
651
652    fn into_content(self, txn: &mut TransactionMut) -> (ItemContent, Option<Self>) {
653        if txn.parent_doc().is_some() {
654            panic!("Cannot integrate the document, because it's already being used as a sub-document elsewhere");
655        }
656        (ItemContent::Doc(None, self), None)
657    }
658
659    fn integrate(self, _txn: &mut TransactionMut, _inner_ref: BranchPtr) {}
660}
661
662/// For a Yjs compatibility reasons we expect subdocuments to be compared based on their reference
663/// equality. This concept however doesn't really exists in Rust. Therefore we use a store reference
664/// instead and specialize it for this single scenario.
665#[repr(transparent)]
666#[derive(Debug, Copy, Clone, Ord, PartialOrd, Eq, PartialEq, Hash)]
667pub(crate) struct DocAddr(usize);
668
669impl DocAddr {
670    pub fn new(doc: &Doc) -> Self {
671        let ptr = Arc::as_ptr(&doc.store.0);
672        DocAddr(ptr as usize)
673    }
674}
675
676#[cfg(test)]
677mod test {
678    use crate::block::{Block, BlockRange, ClientID, ItemContent};
679    use crate::error::Error;
680    use crate::test_utils::{exchange_updates, Blocks};
681    use crate::transaction::{ReadTxn, TransactionMut};
682    use crate::types::ToJson;
683    use crate::update::Update;
684    use crate::updates::decoder::Decode;
685    use crate::updates::encoder::{Encode, Encoder, EncoderV1};
686    use crate::{
687        any, uuid_v4, Any, Array, ArrayPrelim, ArrayRef, Doc, GetString, IdSet, Map, MapRef,
688        OffsetKind, Options, Snapshot, StateVector, Subscription, Text, TextPrelim, TextRef,
689        Transact, Uuid, WriteTxn, XmlElementPrelim, XmlFragment, XmlFragmentRef, XmlTextPrelim,
690        XmlTextRef, ID,
691    };
692    use arc_swap::ArcSwapOption;
693    use assert_matches2::assert_matches;
694    use std::collections::BTreeSet;
695    use std::iter::FromIterator;
696    use std::sync::atomic::{AtomicU32, Ordering};
697    use std::sync::{Arc, Mutex};
698
699    #[test]
700    fn apply_update_basic_v1() {
701        /* Result of calling following code:
702        ```javascript
703        const doc = new Y.Doc()
704        const ytext = doc.getText('type')
705        doc.transact(function () {
706            for (let i = 0; i < 3; i++) {
707                ytext.insert(0, (i % 10).toString())
708            }
709        })
710        const update = Y.encodeStateAsUpdate(doc)
711        ```
712         */
713        let update = &[
714            1, 3, 227, 214, 245, 198, 5, 0, 4, 1, 4, 116, 121, 112, 101, 1, 48, 68, 227, 214, 245,
715            198, 5, 0, 1, 49, 68, 227, 214, 245, 198, 5, 1, 1, 50, 0,
716        ];
717        let doc = Doc::new();
718        let txt = doc.get_or_insert_text("type");
719        let mut txn = doc.transact_mut();
720        txn.apply_update(Update::decode_v1(update).unwrap())
721            .unwrap();
722
723        let actual = txt.get_string(&txn);
724        assert_eq!(actual, "210".to_owned());
725    }
726
727    #[test]
728    fn apply_update_basic_v2() {
729        /* Result of calling following code:
730        ```javascript
731        const doc = new Y.Doc()
732        const ytext = doc.getText('type')
733        doc.transact(function () {
734            for (let i = 0; i < 3; i++) {
735                ytext.insert(0, (i % 10).toString())
736            }
737        })
738        const update = Y.encodeStateAsUpdateV2(doc)
739        ```
740         */
741        let update = &[
742            0, 0, 6, 195, 187, 207, 162, 7, 1, 0, 2, 0, 2, 3, 4, 0, 68, 11, 7, 116, 121, 112, 101,
743            48, 49, 50, 4, 65, 1, 1, 1, 0, 0, 1, 3, 0, 0,
744        ];
745        let doc = Doc::new();
746        let txt = doc.get_or_insert_text("type");
747        let mut txn = doc.transact_mut();
748        txn.apply_update(Update::decode_v2(update).unwrap())
749            .unwrap();
750
751        let actual = txt.get_string(&txn);
752        assert_eq!(actual, "210".to_owned());
753    }
754
755    #[test]
756    fn encode_basic() {
757        let doc = Doc::with_client_id(1490905955);
758        let txt = doc.get_or_insert_text("type");
759        let mut t = doc.transact_mut();
760        txt.insert(&mut t, 0, "0");
761        txt.insert(&mut t, 0, "1");
762        txt.insert(&mut t, 0, "2");
763
764        let encoded = t.encode_state_as_update_v1(&StateVector::default());
765        let expected = &[
766            1, 3, 227, 214, 245, 198, 5, 0, 4, 1, 4, 116, 121, 112, 101, 1, 48, 68, 227, 214, 245,
767            198, 5, 0, 1, 49, 68, 227, 214, 245, 198, 5, 1, 1, 50, 0,
768        ];
769        assert_eq!(encoded.as_slice(), expected);
770    }
771
772    #[test]
773    fn integrate() {
774        // create new document at A and add some initial text to it
775        let d1 = Doc::new();
776        let txt = d1.get_or_insert_text("test");
777        let mut t1 = d1.transact_mut();
778        // Question: why YText.insert uses positions of blocks instead of actual cursor positions
779        // in text as seen by user?
780        txt.insert(&mut t1, 0, "hello");
781        txt.insert(&mut t1, 5, " ");
782        txt.insert(&mut t1, 6, "world");
783
784        assert_eq!(txt.get_string(&t1), "hello world".to_string());
785
786        // create document at B
787        let d2 = Doc::new();
788        let txt = d2.get_or_insert_text("test");
789        let mut t2 = d2.transact_mut();
790        let sv = t2.state_vector().encode_v1();
791
792        // create an update A->B based on B's state vector
793        let mut encoder = EncoderV1::new();
794        t1.encode_diff(
795            &StateVector::decode_v1(sv.as_slice()).unwrap(),
796            &mut encoder,
797        );
798        let binary = encoder.to_vec();
799
800        // decode an update incoming from A and integrate it at B
801        let update = Update::decode_v1(binary.as_slice()).unwrap();
802        let pending = update.integrate(&mut t2).unwrap();
803
804        assert!(pending.0.is_none());
805        assert!(pending.1.is_none());
806
807        // check if B sees the same thing that A does
808        assert_eq!(txt.get_string(&t1), "hello world".to_string());
809    }
810
811    #[test]
812    fn on_update() {
813        let counter = Arc::new(AtomicU32::new(0));
814        let doc = Doc::new();
815        let doc2 = Doc::new();
816        let c = counter.clone();
817        let sub = doc2.observe_update_v1(move |_, e| {
818            let u = Update::decode_v1(&e.update).unwrap();
819            let blocks = Blocks::new(&u.blocks);
820            for block in blocks {
821                c.fetch_add(block.len(), Ordering::SeqCst);
822            }
823        });
824        let txt = doc.get_or_insert_text("test");
825        let mut txn = doc.transact_mut();
826        {
827            txt.insert(&mut txn, 0, "abc");
828            let mut txn2 = doc2.transact_mut();
829            let sv = txn2.state_vector().encode_v1();
830            let u = txn.encode_diff_v1(&StateVector::decode_v1(sv.as_slice()).unwrap());
831            txn2.apply_update(Update::decode_v1(u.as_slice()).unwrap())
832                .unwrap();
833        }
834        assert_eq!(counter.load(Ordering::SeqCst), 3); // update has been propagated
835
836        drop(sub);
837
838        {
839            txt.insert(&mut txn, 3, "de");
840            let mut txn2 = doc2.transact_mut();
841            let sv = txn2.state_vector().encode_v1();
842            let u = txn.encode_diff_v1(&StateVector::decode_v1(sv.as_slice()).unwrap());
843            txn2.apply_update(Update::decode_v1(u.as_slice()).unwrap())
844                .unwrap();
845        }
846        assert_eq!(counter.load(Ordering::SeqCst), 3); // since subscription has been dropped, update was not propagated
847    }
848
849    #[test]
850    #[cfg(feature = "small-client")]
851    fn pending_update_integration() {
852        let doc = Doc::new();
853        let txt = doc.get_or_insert_text("source");
854
855        let updates = [
856            vec![
857                1, 2, 242, 196, 218, 129, 3, 0, 40, 1, 5, 115, 116, 97, 116, 101, 5, 100, 105, 114,
858                116, 121, 1, 121, 40, 1, 7, 99, 111, 110, 116, 101, 120, 116, 4, 112, 97, 116, 104,
859                1, 119, 13, 117, 110, 116, 105, 116, 108, 101, 100, 52, 46, 116, 120, 116, 0,
860            ],
861            vec![
862                1, 1, 242, 196, 218, 129, 3, 2, 40, 1, 7, 99, 111, 110, 116, 101, 120, 116, 13,
863                108, 97, 115, 116, 95, 109, 111, 100, 105, 102, 105, 101, 100, 1, 119, 27, 50, 48,
864                50, 50, 45, 48, 52, 45, 49, 51, 84, 49, 48, 58, 49, 48, 58, 53, 55, 46, 48, 55, 51,
865                54, 50, 51, 90, 0,
866            ],
867            vec![
868                1, 2, 242, 196, 218, 129, 3, 3, 4, 1, 6, 115, 111, 117, 114, 99, 101, 1, 97, 168,
869                242, 196, 218, 129, 3, 0, 1, 120, 0,
870            ],
871            vec![
872                1, 1, 242, 196, 218, 129, 3, 4, 168, 242, 196, 218, 129, 3, 0, 1, 120, 1, 242, 196,
873                218, 129, 3, 1, 0, 1,
874            ],
875            vec![
876                1, 1, 152, 182, 129, 244, 193, 193, 227, 4, 0, 168, 242, 196, 218, 129, 3, 4, 1,
877                121, 1, 242, 196, 218, 129, 3, 2, 0, 1, 4, 1,
878            ],
879            vec![
880                1, 2, 242, 196, 218, 129, 3, 5, 132, 242, 196, 218, 129, 3, 3, 1, 98, 168, 152,
881                190, 167, 244, 1, 0, 1, 120, 0,
882            ],
883            vec![
884                1, 1, 242, 196, 218, 129, 3, 6, 168, 152, 190, 167, 244, 1, 0, 1, 120, 1, 152, 190,
885                167, 244, 1, 1, 0, 1,
886            ],
887            vec![
888                1, 1, 242, 196, 218, 129, 3, 7, 132, 242, 196, 218, 129, 3, 5, 1, 99, 0,
889            ],
890            vec![
891                1, 1, 242, 196, 218, 129, 3, 8, 132, 242, 196, 218, 129, 3, 7, 1, 100, 0,
892            ],
893        ];
894
895        for u in updates {
896            let mut txn = doc.transact_mut();
897            let u = Update::decode_v1(u.as_slice()).unwrap();
898            println!("integrate pending update: {u:#?}");
899            txn.apply_update(u).unwrap();
900        }
901        assert_eq!(txt.get_string(&doc.transact()), "abcd".to_string());
902    }
903
904    #[test]
905    fn ypy_issue_32() {
906        let d1 = Doc::with_client_id(1971027812);
907        let source_1 = d1.get_or_insert_text("source");
908        source_1.push(&mut d1.transact_mut(), "a");
909
910        let updates = [
911            vec![
912                1, 2, 201, 210, 153, 56, 0, 40, 1, 5, 115, 116, 97, 116, 101, 5, 100, 105, 114,
913                116, 121, 1, 121, 40, 1, 7, 99, 111, 110, 116, 101, 120, 116, 4, 112, 97, 116, 104,
914                1, 119, 13, 117, 110, 116, 105, 116, 108, 101, 100, 52, 46, 116, 120, 116, 0,
915            ],
916            vec![
917                1, 1, 201, 210, 153, 56, 2, 168, 201, 210, 153, 56, 0, 1, 120, 1, 201, 210, 153,
918                56, 1, 0, 1,
919            ],
920            vec![
921                1, 1, 201, 210, 153, 56, 3, 40, 1, 7, 99, 111, 110, 116, 101, 120, 116, 13, 108,
922                97, 115, 116, 95, 109, 111, 100, 105, 102, 105, 101, 100, 1, 119, 27, 50, 48, 50,
923                50, 45, 48, 52, 45, 49, 54, 84, 49, 52, 58, 48, 51, 58, 53, 51, 46, 57, 51, 48, 52,
924                54, 56, 90, 0,
925            ],
926            vec![
927                1, 1, 201, 210, 153, 56, 4, 168, 201, 210, 153, 56, 2, 1, 121, 1, 201, 210, 153,
928                56, 1, 2, 1,
929            ],
930        ];
931        for u in updates {
932            let u = Update::decode_v1(&u).unwrap();
933            d1.transact_mut().apply_update(u).unwrap();
934        }
935
936        assert_eq!("a", source_1.get_string(&d1.transact()));
937
938        let d2 = Doc::new();
939        let source_2 = d2.get_or_insert_text("source");
940        let state_2 = d2.transact().state_vector().encode_v1();
941        let update = d1
942            .transact()
943            .encode_state_as_update_v1(&StateVector::decode_v1(&state_2).unwrap());
944        let update = Update::decode_v1(&update).unwrap();
945        d2.transact_mut().apply_update(update).unwrap();
946
947        assert_eq!("a", source_2.get_string(&d2.transact()));
948
949        let update = Update::decode_v1(&[
950            1, 2, 201, 210, 153, 56, 5, 132, 228, 254, 237, 171, 7, 0, 1, 98, 168, 201, 210, 153,
951            56, 4, 1, 120, 0,
952        ])
953        .unwrap();
954        d1.transact_mut().apply_update(update).unwrap();
955        assert_eq!("ab", source_1.get_string(&d1.transact()));
956
957        let d3 = Doc::new();
958        let source_3 = d3.get_or_insert_text("source");
959        let state_3 = d3.transact().state_vector().encode_v1();
960        let state_3 = StateVector::decode_v1(&state_3).unwrap();
961        let update = d1.transact().encode_state_as_update_v1(&state_3);
962        let update = Update::decode_v1(&update).unwrap();
963        d3.transact_mut().apply_update(update).unwrap();
964
965        assert_eq!("ab", source_3.get_string(&d3.transact()));
966    }
967
968    #[test]
969    fn observe_transaction_cleanup() {
970        // Setup
971        let doc = Doc::new();
972        let text = doc.get_or_insert_text("test");
973        let before_state = Arc::new(ArcSwapOption::default());
974        let after_state = Arc::new(ArcSwapOption::default());
975        let delete_set = Arc::new(ArcSwapOption::default());
976        // Create interior mutable references for the callback.
977        let before_ref = before_state.clone();
978        let after_ref = after_state.clone();
979        let delete_ref = delete_set.clone();
980        // Subscribe callback
981
982        let sub: Subscription = doc
983            .observe_transaction_cleanup(move |_: &TransactionMut, event| {
984                before_ref.store(Some(event.before_state.clone().into()));
985                after_ref.store(Some(event.after_state.clone().into()));
986                delete_ref.store(Some(event.delete_set.clone().into()));
987            })
988            .unwrap();
989
990        {
991            let mut txn = doc.transact_mut();
992
993            // Update the document
994            text.insert(&mut txn, 0, "abc");
995            text.remove_range(&mut txn, 1, 2);
996            txn.commit();
997
998            // Compare values
999            assert_eq!(
1000                before_state.swap(None),
1001                Some(Arc::new(txn.before_state().clone()))
1002            );
1003            assert_eq!(
1004                after_state.swap(None),
1005                Some(Arc::new(txn.after_state().clone()))
1006            );
1007            assert_eq!(
1008                delete_set.swap(None),
1009                Some(Arc::new(txn.delete_set.clone()))
1010            );
1011        }
1012
1013        // Ensure that the subscription is successfully dropped.
1014        drop(sub);
1015        let mut txn = doc.transact_mut();
1016        text.insert(&mut txn, 0, "should not update");
1017        txn.commit();
1018        assert_ne!(
1019            after_state.swap(None),
1020            Some(Arc::new(txn.after_state().clone()))
1021        );
1022    }
1023
1024    #[test]
1025    fn partially_duplicated_update() {
1026        let d1 = Doc::with_client_id(1);
1027        let txt1 = d1.get_or_insert_text("text");
1028        txt1.insert(&mut d1.transact_mut(), 0, "hello");
1029        let u = d1
1030            .transact()
1031            .encode_state_as_update_v1(&StateVector::default());
1032
1033        let d2 = Doc::with_client_id(2);
1034        let txt2 = d2.get_or_insert_text("text");
1035        d2.transact_mut()
1036            .apply_update(Update::decode_v1(&u).unwrap())
1037            .unwrap();
1038
1039        txt1.insert(&mut d1.transact_mut(), 5, "world");
1040        let u = d1
1041            .transact()
1042            .encode_state_as_update_v1(&StateVector::default());
1043        d2.transact_mut()
1044            .apply_update(Update::decode_v1(&u).unwrap())
1045            .unwrap();
1046
1047        assert_eq!(
1048            txt1.get_string(&d1.transact()),
1049            txt2.get_string(&d2.transact())
1050        );
1051    }
1052
1053    #[test]
1054    fn incremental_observe_update() {
1055        const INPUT: &'static str = "hello";
1056
1057        let d1 = Doc::with_client_id(1);
1058        let txt1 = d1.get_or_insert_text("text");
1059        let acc = Arc::new(Mutex::new(String::new()));
1060
1061        let a = acc.clone();
1062        let _sub = d1.observe_update_v1(move |_: &TransactionMut, e| {
1063            let u = Update::decode_v1(&e.update).unwrap();
1064            for mut block in u.blocks.into_blocks(false) {
1065                if let Block::Item(item) = block {
1066                    if let ItemContent::String(s) = &item.content {
1067                        // each character is appended in individual transaction 1-by-1,
1068                        // therefore each update should contain a single string with only
1069                        // one element
1070                        let mut aref = a.lock().unwrap();
1071                        aref.push_str(s.as_str());
1072                    } else {
1073                        panic!("unexpected content type")
1074                    }
1075                }
1076            }
1077        });
1078
1079        for c in INPUT.chars() {
1080            // append characters 1-by-1 (1 transactions per character)
1081            txt1.push(&mut d1.transact_mut(), &c.to_string());
1082        }
1083
1084        assert_eq!(acc.lock().unwrap().as_str(), INPUT);
1085
1086        // test incremental deletes
1087        let acc = Arc::new(Mutex::new(vec![]));
1088        let a = acc.clone();
1089        let _sub = d1.observe_update_v1(move |_: &TransactionMut, e| {
1090            let u = Update::decode_v1(&e.update).unwrap();
1091            for (&client_id, range) in u.delete_set.iter() {
1092                if client_id == ClientID::new(1) {
1093                    let mut aref = a.lock().unwrap();
1094                    for r in range.iter() {
1095                        aref.push(r.clone());
1096                    }
1097                }
1098            }
1099        });
1100
1101        for _ in 0..INPUT.len() as u32 {
1102            txt1.remove_range(&mut d1.transact_mut(), 0, 1);
1103        }
1104
1105        let expected = vec![(0..1), (1..2), (2..3), (3..4), (4..5)];
1106        assert_eq!(&*acc.lock().unwrap(), &expected);
1107    }
1108
1109    #[test]
1110    fn ycrdt_issue_174() {
1111        let doc = Doc::new();
1112        let bin = &[
1113            0, 0, 11, 176, 133, 128, 149, 31, 205, 190, 199, 196, 21, 7, 3, 0, 3, 5, 0, 17, 168, 1,
1114            8, 0, 40, 0, 8, 0, 40, 0, 8, 0, 40, 0, 33, 1, 39, 110, 91, 49, 49, 49, 114, 111, 111,
1115            116, 105, 51, 50, 114, 111, 111, 116, 115, 116, 114, 105, 110, 103, 114, 111, 111, 116,
1116            97, 95, 108, 105, 115, 116, 114, 111, 111, 116, 97, 95, 109, 97, 112, 114, 111, 111,
1117            116, 105, 51, 50, 95, 108, 105, 115, 116, 114, 111, 111, 116, 105, 51, 50, 95, 109, 97,
1118            112, 114, 111, 111, 116, 115, 116, 114, 105, 110, 103, 95, 108, 105, 115, 116, 114,
1119            111, 111, 116, 115, 116, 114, 105, 110, 103, 95, 109, 97, 112, 65, 1, 4, 3, 4, 6, 4, 6,
1120            4, 5, 4, 8, 4, 7, 4, 11, 4, 10, 3, 0, 5, 1, 6, 0, 1, 0, 1, 0, 1, 2, 65, 8, 2, 8, 0,
1121            125, 2, 119, 5, 119, 111, 114, 108, 100, 118, 2, 1, 98, 119, 1, 97, 1, 97, 125, 1, 118,
1122            2, 1, 98, 119, 1, 98, 1, 97, 125, 2, 125, 1, 125, 2, 119, 1, 97, 119, 1, 98, 8, 0, 1,
1123            141, 223, 163, 226, 10, 1, 0, 1,
1124        ];
1125        let update = Update::decode_v2(bin).unwrap();
1126        doc.transact_mut().apply_update(update).unwrap();
1127
1128        let root = doc.get_or_insert_map("root");
1129        let actual = root.to_json(&doc.transact());
1130        let expected = Any::from_json(
1131            r#"{
1132              "string": "world",
1133              "a_list": [{"b": "a", "a": 1}],
1134              "i32_map": {"1": 2},
1135              "a_map": {
1136                "1": {"a": 2, "b": "b"}
1137              },
1138              "string_list": ["a"],
1139              "i32": 2,
1140              "string_map": {"1": "b"},
1141              "i32_list": [1]
1142            }"#,
1143        )
1144        .unwrap();
1145        assert_eq!(actual, expected);
1146    }
1147
1148    #[test]
1149    fn snapshots_splitting_text() {
1150        let mut options = Options::with_client_id(ClientID::new(1));
1151        options.skip_gc = true;
1152
1153        let d1 = Doc::with_options(options);
1154        let txt1 = d1.get_or_insert_text("text");
1155        txt1.insert(&mut d1.transact_mut(), 0, "hello");
1156        let snapshot = d1.transact_mut().snapshot();
1157        txt1.insert(&mut d1.transact_mut(), 5, "_world");
1158
1159        let mut encoder = EncoderV1::new();
1160        d1.transact_mut()
1161            .encode_state_from_snapshot(&snapshot, &mut encoder)
1162            .unwrap();
1163        let update = Update::decode_v1(&encoder.to_vec()).unwrap();
1164
1165        let d2 = Doc::with_client_id(2);
1166        let txt2 = d2.get_or_insert_text("text");
1167        d2.transact_mut().apply_update(update).unwrap();
1168
1169        assert_eq!(txt2.get_string(&d2.transact()), "hello".to_string());
1170    }
1171
1172    #[test]
1173    fn snapshot_non_splitting_text() {
1174        let mut options = Options::default();
1175        options.skip_gc = true;
1176
1177        let doc = Doc::with_options(options.clone().into());
1178        let txt = doc.get_or_insert_text("name");
1179
1180        let mut txn = doc.transact_mut();
1181        txt.insert(&mut txn, 0, "Lucas");
1182        drop(txn);
1183
1184        let txn = doc.transact();
1185        let snapshot = txn.snapshot();
1186
1187        let mut encoder = EncoderV1::new();
1188        txn.encode_state_from_snapshot(&snapshot, &mut encoder)
1189            .unwrap();
1190        let state_diff = encoder.to_vec();
1191
1192        let remote_doc = Doc::with_options(options);
1193        let remote_txt = remote_doc.get_or_insert_text("name");
1194        let mut txn = remote_doc.transact_mut();
1195        let update = Update::decode_v1(&state_diff).unwrap();
1196        txn.apply_update(update).unwrap();
1197
1198        let actual = remote_txt.get_string(&txn);
1199
1200        assert_eq!(actual, "Lucas");
1201    }
1202
1203    #[test]
1204    fn yrb_issue_45() {
1205        let diffs: Vec<Vec<u8>> = vec![
1206            vec![
1207                1, 3, 197, 134, 244, 186, 10, 0, 7, 1, 7, 100, 101, 102, 97, 117, 108, 116, 3, 9,
1208                112, 97, 114, 97, 103, 114, 97, 112, 104, 7, 0, 197, 134, 244, 186, 10, 0, 6, 4, 0,
1209                197, 134, 244, 186, 10, 1, 1, 115, 0,
1210            ],
1211            vec![
1212                1, 1, 197, 134, 244, 186, 10, 3, 132, 197, 134, 244, 186, 10, 2, 3, 227, 129, 149,
1213                1, 197, 134, 244, 186, 10, 1, 2, 1,
1214            ],
1215            vec![
1216                1, 4, 197, 134, 244, 186, 10, 0, 7, 1, 7, 100, 101, 102, 97, 117, 108, 116, 3, 9,
1217                112, 97, 114, 97, 103, 114, 97, 112, 104, 7, 0, 197, 134, 244, 186, 10, 0, 6, 1, 0,
1218                197, 134, 244, 186, 10, 1, 1, 132, 197, 134, 244, 186, 10, 2, 3, 227, 129, 149, 1,
1219                197, 134, 244, 186, 10, 1, 2, 1,
1220            ],
1221            vec![
1222                1, 1, 197, 134, 244, 186, 10, 4, 132, 197, 134, 244, 186, 10, 3, 1, 120, 0,
1223            ],
1224            vec![
1225                1, 1, 197, 134, 244, 186, 10, 5, 132, 197, 134, 244, 186, 10, 4, 3, 227, 129, 129,
1226                1, 197, 134, 244, 186, 10, 1, 4, 1,
1227            ],
1228            vec![
1229                1, 1, 197, 134, 244, 186, 10, 6, 132, 197, 134, 244, 186, 10, 5, 1, 107, 0,
1230            ],
1231            vec![
1232                1, 2, 197, 134, 244, 186, 10, 4, 129, 197, 134, 244, 186, 10, 3, 1, 132, 197, 134,
1233                244, 186, 10, 4, 3, 227, 129, 129, 1, 197, 134, 244, 186, 10, 1, 4, 1,
1234            ],
1235            vec![
1236                1, 1, 197, 134, 244, 186, 10, 7, 132, 197, 134, 244, 186, 10, 6, 3, 227, 129, 147,
1237                1, 197, 134, 244, 186, 10, 1, 6, 1,
1238            ],
1239            vec![
1240                1, 2, 197, 134, 244, 186, 10, 6, 129, 197, 134, 244, 186, 10, 5, 1, 132, 197, 134,
1241                244, 186, 10, 6, 3, 227, 129, 147, 1, 197, 134, 244, 186, 10, 1, 6, 1,
1242            ],
1243            vec![
1244                1, 1, 197, 134, 244, 186, 10, 8, 132, 197, 134, 244, 186, 10, 7, 1, 114, 0,
1245            ],
1246            vec![
1247                1, 1, 197, 134, 244, 186, 10, 9, 132, 197, 134, 244, 186, 10, 8, 3, 227, 130, 140,
1248                1, 197, 134, 244, 186, 10, 1, 8, 1,
1249            ],
1250            vec![
1251                1, 1, 197, 134, 244, 186, 10, 8, 132, 197, 134, 244, 186, 10, 7, 1, 114, 0,
1252            ],
1253            vec![
1254                1, 1, 197, 134, 244, 186, 10, 10, 132, 197, 134, 244, 186, 10, 9, 1, 107, 0,
1255            ],
1256            vec![
1257                1, 1, 197, 134, 244, 186, 10, 11, 132, 197, 134, 244, 186, 10, 10, 3, 227, 129,
1258                139, 1, 197, 134, 244, 186, 10, 1, 10, 1,
1259            ],
1260            vec![
1261                1, 1, 197, 134, 244, 186, 10, 12, 132, 197, 134, 244, 186, 10, 11, 1, 114, 0,
1262            ],
1263            vec![
1264                1, 1, 197, 134, 244, 186, 10, 13, 132, 197, 134, 244, 186, 10, 12, 3, 227, 130,
1265                137, 1, 197, 134, 244, 186, 10, 1, 12, 1,
1266            ],
1267            vec![
1268                1, 1, 197, 134, 244, 186, 10, 9, 132, 197, 134, 244, 186, 10, 8, 3, 227, 130, 140,
1269                1, 197, 134, 244, 186, 10, 1, 8, 1,
1270            ],
1271            vec![
1272                1, 1, 197, 134, 244, 186, 10, 10, 132, 197, 134, 244, 186, 10, 9, 1, 107, 0,
1273            ],
1274            vec![
1275                1, 1, 197, 134, 244, 186, 10, 11, 132, 197, 134, 244, 186, 10, 10, 3, 227, 129,
1276                139, 1, 197, 134, 244, 186, 10, 1, 10, 1,
1277            ],
1278            vec![
1279                1, 1, 197, 134, 244, 186, 10, 12, 132, 197, 134, 244, 186, 10, 11, 1, 114, 0,
1280            ],
1281            vec![
1282                1, 1, 197, 134, 244, 186, 10, 14, 132, 197, 134, 244, 186, 10, 13, 1, 98, 0,
1283            ],
1284            vec![
1285                1, 1, 197, 134, 244, 186, 10, 16, 132, 197, 134, 244, 186, 10, 15, 1, 103, 0,
1286            ],
1287            vec![
1288                1, 1, 197, 134, 244, 186, 10, 15, 132, 197, 134, 244, 186, 10, 14, 3, 227, 129,
1289                176, 1, 197, 134, 244, 186, 10, 1, 14, 1,
1290            ],
1291            vec![
1292                1, 1, 197, 134, 244, 186, 10, 17, 132, 197, 134, 244, 186, 10, 16, 3, 227, 129,
1293                144, 1, 197, 134, 244, 186, 10, 1, 16, 1,
1294            ],
1295            vec![
1296                1, 1, 197, 134, 244, 186, 10, 17, 132, 197, 134, 244, 186, 10, 16, 3, 227, 129,
1297                144, 1, 197, 134, 244, 186, 10, 1, 16, 1,
1298            ],
1299            vec![
1300                1, 1, 197, 134, 244, 186, 10, 18, 132, 197, 134, 244, 186, 10, 17, 6, 227, 131,
1301                144, 227, 130, 176, 1, 197, 134, 244, 186, 10, 2, 15, 1, 17, 1,
1302            ],
1303            vec![
1304                1, 1, 197, 134, 244, 186, 10, 20, 132, 197, 134, 244, 186, 10, 19, 1, 103, 0,
1305            ],
1306            vec![
1307                1, 3, 197, 134, 244, 186, 10, 13, 132, 197, 134, 244, 186, 10, 12, 3, 227, 130,
1308                137, 129, 197, 134, 244, 186, 10, 13, 1, 132, 197, 134, 244, 186, 10, 14, 4, 227,
1309                129, 176, 103, 1, 197, 134, 244, 186, 10, 2, 12, 1, 14, 1,
1310            ],
1311            vec![
1312                1, 1, 197, 134, 244, 186, 10, 21, 132, 197, 134, 244, 186, 10, 20, 3, 227, 129,
1313                140, 1, 197, 134, 244, 186, 10, 1, 20, 1,
1314            ],
1315            vec![
1316                1, 1, 197, 134, 244, 186, 10, 23, 132, 197, 134, 244, 186, 10, 22, 3, 227, 129,
1317                170, 1, 197, 134, 244, 186, 10, 1, 22, 1,
1318            ],
1319            vec![
1320                1, 3, 197, 134, 244, 186, 10, 18, 132, 197, 134, 244, 186, 10, 17, 6, 227, 131,
1321                144, 227, 130, 176, 129, 197, 134, 244, 186, 10, 19, 1, 132, 197, 134, 244, 186,
1322                10, 20, 3, 227, 129, 140, 1, 197, 134, 244, 186, 10, 3, 15, 1, 17, 1, 20, 1,
1323            ],
1324            vec![
1325                1, 1, 197, 134, 244, 186, 10, 24, 132, 197, 134, 244, 186, 10, 23, 3, 227, 129,
1326                132, 0,
1327            ],
1328            vec![
1329                1, 1, 197, 134, 244, 186, 10, 22, 132, 197, 134, 244, 186, 10, 21, 1, 110, 0,
1330            ],
1331            vec![
1332                1, 1, 197, 134, 244, 186, 10, 26, 132, 197, 134, 244, 186, 10, 25, 3, 227, 129,
1333                139, 1, 197, 134, 244, 186, 10, 1, 25, 1,
1334            ],
1335            vec![
1336                1, 1, 197, 134, 244, 186, 10, 25, 132, 197, 134, 244, 186, 10, 24, 1, 107, 0,
1337            ],
1338            vec![
1339                1, 4, 197, 134, 244, 186, 10, 22, 129, 197, 134, 244, 186, 10, 21, 1, 132, 197,
1340                134, 244, 186, 10, 22, 6, 227, 129, 170, 227, 129, 132, 129, 197, 134, 244, 186,
1341                10, 24, 1, 132, 197, 134, 244, 186, 10, 25, 3, 227, 129, 139, 1, 197, 134, 244,
1342                186, 10, 2, 22, 1, 25, 1,
1343            ],
1344            vec![
1345                1, 1, 197, 134, 244, 186, 10, 27, 132, 197, 134, 244, 186, 10, 26, 1, 100, 0,
1346            ],
1347            vec![
1348                1, 1, 197, 134, 244, 186, 10, 28, 132, 197, 134, 244, 186, 10, 27, 3, 227, 129,
1349                169, 1, 197, 134, 244, 186, 10, 1, 27, 1,
1350            ],
1351            vec![
1352                1, 2, 197, 134, 244, 186, 10, 27, 129, 197, 134, 244, 186, 10, 26, 1, 132, 197,
1353                134, 244, 186, 10, 27, 3, 227, 129, 169, 1, 197, 134, 244, 186, 10, 1, 27, 1,
1354            ],
1355            vec![
1356                1, 1, 197, 134, 244, 186, 10, 29, 132, 197, 134, 244, 186, 10, 28, 3, 227, 129,
1357                134, 0,
1358            ],
1359            vec![
1360                1, 1, 197, 134, 244, 186, 10, 30, 132, 197, 134, 244, 186, 10, 29, 1, 107, 0,
1361            ],
1362            vec![
1363                1, 1, 197, 134, 244, 186, 10, 29, 132, 197, 134, 244, 186, 10, 28, 3, 227, 129,
1364                134, 0,
1365            ],
1366            vec![
1367                1, 1, 197, 134, 244, 186, 10, 31, 132, 197, 134, 244, 186, 10, 30, 3, 227, 129,
1368                139, 1, 197, 134, 244, 186, 10, 1, 30, 1,
1369            ],
1370            vec![
1371                1, 1, 197, 134, 244, 186, 10, 30, 132, 197, 134, 244, 186, 10, 29, 1, 107, 0,
1372            ],
1373            vec![
1374                1, 1, 197, 134, 244, 186, 10, 31, 132, 197, 134, 244, 186, 10, 30, 3, 227, 129,
1375                139, 1, 197, 134, 244, 186, 10, 1, 30, 1,
1376            ],
1377            vec![
1378                1, 1, 197, 134, 244, 186, 10, 32, 135, 197, 134, 244, 186, 10, 0, 3, 9, 112, 97,
1379                114, 97, 103, 114, 97, 112, 104, 0,
1380            ],
1381            vec![
1382                1, 1, 197, 134, 244, 186, 10, 32, 135, 197, 134, 244, 186, 10, 0, 3, 9, 112, 97,
1383                114, 97, 103, 114, 97, 112, 104, 0,
1384            ],
1385            vec![
1386                1, 2, 197, 134, 244, 186, 10, 33, 7, 0, 197, 134, 244, 186, 10, 32, 6, 4, 0, 197,
1387                134, 244, 186, 10, 33, 1, 107, 0,
1388            ],
1389            vec![
1390                1, 1, 197, 134, 244, 186, 10, 35, 132, 197, 134, 244, 186, 10, 34, 3, 227, 129,
1391                139, 1, 197, 134, 244, 186, 10, 1, 34, 1,
1392            ],
1393            vec![
1394                1, 1, 197, 134, 244, 186, 10, 36, 132, 197, 134, 244, 186, 10, 35, 1, 107, 0,
1395            ],
1396        ];
1397
1398        let doc = Doc::new();
1399        let mut txn = doc.transact_mut();
1400        for diff in diffs {
1401            let u = Update::decode_v1(diff.as_slice()).unwrap();
1402            txn.apply_update(u).unwrap();
1403        }
1404    }
1405
1406    #[test]
1407    fn root_refs() {
1408        let doc = Doc::new();
1409        {
1410            let _txt = doc.get_or_insert_text("text");
1411            let _array = doc.get_or_insert_array("array");
1412            let _map = doc.get_or_insert_map("map");
1413            let _xml_elem = doc.get_or_insert_xml_fragment("xml_elem");
1414        }
1415
1416        let txn = doc.transact();
1417        for (key, value) in txn.root_refs() {
1418            match key {
1419                "text" => assert!(value.cast::<TextRef>().is_ok()),
1420                "array" => assert!(value.cast::<ArrayRef>().is_ok()),
1421                "map" => assert!(value.cast::<MapRef>().is_ok()),
1422                "xml_elem" => assert!(value.cast::<XmlFragmentRef>().is_ok()),
1423                "xml_text" => assert!(value.cast::<XmlTextRef>().is_ok()),
1424                other => panic!("unrecognized root type: '{}'", other),
1425            }
1426        }
1427    }
1428
1429    #[test]
1430    fn integrate_block_with_parent_gc() {
1431        let d1 = Doc::with_client_id(1);
1432        let d2 = Doc::with_client_id(2);
1433        let d3 = Doc::with_client_id(3);
1434
1435        {
1436            let root = d1.get_or_insert_array("array");
1437            let mut txn = d1.transact_mut();
1438            root.push_back(&mut txn, ArrayPrelim::from(["A"]));
1439        }
1440
1441        exchange_updates(&[&d1, &d2, &d3]);
1442
1443        {
1444            let root = d2.get_or_insert_array("array");
1445            let mut t2 = d2.transact_mut();
1446            root.remove(&mut t2, 0);
1447            d1.transact_mut()
1448                .apply_update(Update::decode_v1(&t2.encode_update_v1()).unwrap())
1449                .unwrap();
1450        }
1451
1452        {
1453            let root = d3.get_or_insert_array("array");
1454            let mut t3 = d3.transact_mut();
1455            let a3 = root.get(&t3, 0).unwrap().cast::<ArrayRef>().unwrap();
1456            a3.push_back(&mut t3, "B");
1457            // D1 got update which already removed a3, but this must not cause panic
1458            d1.transact_mut()
1459                .apply_update(Update::decode_v1(&t3.encode_update_v1()).unwrap())
1460                .unwrap();
1461        }
1462
1463        exchange_updates(&[&d1, &d2, &d3]);
1464
1465        let r1 = d1.get_or_insert_array("array").to_json(&d1.transact());
1466        let r2 = d2.get_or_insert_array("array").to_json(&d2.transact());
1467        let r3 = d3.get_or_insert_array("array").to_json(&d3.transact());
1468
1469        assert_eq!(r1, r2);
1470        assert_eq!(r2, r3);
1471        assert_eq!(r3, r1);
1472    }
1473
1474    #[test]
1475    fn subdoc() {
1476        let doc = Doc::with_client_id(1);
1477        let event = Arc::new(ArcSwapOption::default());
1478        let event_c = event.clone();
1479        let _sub = doc.observe_subdocs(move |_, e| {
1480            let added = e.added().map(|d| d.guid().clone()).collect();
1481            let removed = e.removed().map(|d| d.guid().clone()).collect();
1482            let loaded = e.loaded().map(|d| d.guid().clone()).collect();
1483            event_c.store(Some(Arc::new((added, removed, loaded))));
1484        });
1485        let subdocs = doc.get_or_insert_map("mysubdocs");
1486        let uuid_a: Uuid = "A".into();
1487        let doc_a = Doc::with_options({
1488            let mut o = Options::default();
1489            o.guid = uuid_a.clone();
1490            o
1491        });
1492        {
1493            let mut txn = doc.transact_mut();
1494            let doc_a_ref = subdocs.insert(&mut txn, "a", doc_a);
1495            doc_a_ref.load(&mut txn);
1496        }
1497
1498        let actual = event.swap(None);
1499        assert_eq!(
1500            actual,
1501            Some((vec![uuid_a.clone()], vec![], vec![uuid_a.clone()]).into())
1502        );
1503
1504        {
1505            let mut txn = doc.transact_mut();
1506            let doc_a_ref = subdocs.get(&txn, "a").unwrap().cast::<Doc>().unwrap();
1507            doc_a_ref.load(&mut txn);
1508        }
1509        let actual = event.swap(None);
1510        assert_eq!(actual, None);
1511
1512        {
1513            let mut txn = doc.transact_mut();
1514            let doc_a_ref = subdocs.get(&txn, "a").unwrap().cast::<Doc>().unwrap();
1515            doc_a_ref.destroy(Some(&mut txn));
1516        }
1517        let actual = event.swap(None);
1518        assert_eq!(
1519            actual,
1520            Some(Arc::new((
1521                vec![uuid_a.clone()],
1522                vec![uuid_a.clone()],
1523                vec![]
1524            )))
1525        );
1526
1527        {
1528            let mut txn = doc.transact_mut();
1529            let doc_a_ref = subdocs.get(&txn, "a").unwrap().cast::<Doc>().unwrap();
1530            doc_a_ref.load(&mut txn);
1531        }
1532        let actual = event.swap(None);
1533        assert_eq!(
1534            actual,
1535            Some(Arc::new((vec![], vec![], vec![uuid_a.clone()])))
1536        );
1537
1538        let doc_b = Doc::with_options({
1539            let mut o = Options::default();
1540            o.guid = uuid_a.clone();
1541            o.should_load = false;
1542            o
1543        });
1544        subdocs.insert(&mut doc.transact_mut(), "b", doc_b);
1545        let actual = event.swap(None);
1546        assert_eq!(
1547            actual,
1548            Some(Arc::new((vec![uuid_a.clone()], vec![], vec![])))
1549        );
1550
1551        {
1552            let mut txn = doc.transact_mut();
1553            let doc_b_ref = subdocs.get(&txn, "b").unwrap().cast::<Doc>().unwrap();
1554            doc_b_ref.load(&mut txn);
1555        }
1556        let actual = event.swap(None);
1557        assert_eq!(
1558            actual,
1559            Some(Arc::new((vec![], vec![], vec![uuid_a.clone()])))
1560        );
1561
1562        let uuid_c: Uuid = "C".into();
1563        let doc_c = Doc::with_options({
1564            let mut o = Options::default();
1565            o.guid = uuid_c.clone();
1566            o
1567        });
1568        {
1569            let mut txn = doc.transact_mut();
1570            let doc_c_ref = subdocs.insert(&mut txn, "c", doc_c);
1571            doc_c_ref.load(&mut txn);
1572        }
1573        let actual = event.swap(None);
1574        assert_eq!(
1575            actual,
1576            Some(Arc::new((
1577                vec![uuid_c.clone()],
1578                vec![],
1579                vec![uuid_c.clone()]
1580            )))
1581        );
1582
1583        let guids: BTreeSet<_> = doc.transact().subdoc_guids().collect();
1584        assert_eq!(guids, BTreeSet::from([uuid_a.clone(), uuid_c.clone()]));
1585
1586        let data = doc
1587            .transact()
1588            .encode_state_as_update_v1(&StateVector::default());
1589
1590        let doc2 = Doc::new();
1591        let event = Arc::new(ArcSwapOption::default());
1592        let event_c = event.clone();
1593        let _sub = doc2.observe_subdocs(move |_, e| {
1594            let added: Vec<_> = e.added().map(|d| d.guid().clone()).collect();
1595            let removed: Vec<_> = e.removed().map(|d| d.guid().clone()).collect();
1596            let loaded: Vec<_> = e.loaded().map(|d| d.guid().clone()).collect();
1597            event_c.store(Some(Arc::new((added, removed, loaded))));
1598        });
1599        let update = Update::decode_v1(&data).unwrap();
1600        doc2.transact_mut().apply_update(update).unwrap();
1601        let mut actual = event.swap(None).unwrap();
1602        Arc::get_mut(&mut actual).unwrap().0.sort();
1603        assert_eq!(
1604            actual,
1605            Arc::new((
1606                vec![uuid_a.clone(), uuid_a.clone(), uuid_c.clone()],
1607                vec![],
1608                vec![]
1609            ))
1610        );
1611
1612        let subdocs = doc2.transact().get_map("mysubdocs").unwrap();
1613        {
1614            let mut txn = doc2.transact_mut();
1615            let doc_ref = subdocs.get(&mut txn, "a").unwrap().cast::<Doc>().unwrap();
1616            doc_ref.load(&mut txn);
1617        }
1618        let actual = event.swap(None);
1619        assert_eq!(
1620            actual,
1621            Some(Arc::new((vec![], vec![], vec![uuid_a.clone()])))
1622        );
1623
1624        let guids: BTreeSet<_> = doc2.transact().subdoc_guids().collect();
1625        assert_eq!(guids, BTreeSet::from([uuid_a.clone(), uuid_c.clone()]));
1626        {
1627            let mut txn = doc2.transact_mut();
1628            subdocs.remove(&mut txn, "a");
1629        }
1630
1631        let actual = event.swap(None);
1632        assert_eq!(
1633            actual,
1634            Some(Arc::new((vec![], vec![uuid_a.clone()], vec![])))
1635        );
1636
1637        let mut guids: Vec<_> = doc2.transact().subdoc_guids().collect();
1638        guids.sort();
1639        assert_eq!(guids, vec![uuid_a.clone(), uuid_c.clone()]);
1640    }
1641
1642    #[test]
1643    fn subdoc_load_edge_cases() {
1644        let doc = Doc::with_client_id(1);
1645        let array = doc.get_or_insert_array("test");
1646        let subdoc_1 = Doc::new();
1647        let uuid_1 = subdoc_1.guid().clone();
1648
1649        let event = Arc::new(ArcSwapOption::default());
1650        let event_c = event.clone();
1651        let _sub = doc.observe_subdocs(move |_, e| {
1652            let added = e.added().map(|d| d.guid().clone()).collect();
1653            let removed = e.removed().map(|d| d.guid().clone()).collect();
1654            let loaded = e.loaded().map(|d| d.guid().clone()).collect();
1655
1656            event_c.store(Some(Arc::new((added, removed, loaded))));
1657        });
1658        let doc_ref = {
1659            let mut txn = doc.transact_mut();
1660            let doc_ref = array.insert(&mut txn, 0, subdoc_1);
1661            assert!(doc_ref.should_load());
1662            assert!(!doc_ref.auto_load());
1663            doc_ref
1664        };
1665        let last_event = event.swap(None);
1666        assert_eq!(
1667            last_event,
1668            Some((vec![uuid_1.clone()], vec![], vec![uuid_1.clone()]).into())
1669        );
1670
1671        // destroy and check whether lastEvent adds it again to added (it shouldn't)
1672        doc_ref.destroy(Some(&mut doc.transact_mut()));
1673        let doc_ref_2 = array
1674            .get(&doc.transact(), 0)
1675            .unwrap()
1676            .cast::<Doc>()
1677            .unwrap();
1678        let uuid_2 = doc_ref_2.guid();
1679        assert!(!Doc::ptr_eq(&doc_ref, &doc_ref_2));
1680
1681        let last_event = event.swap(None);
1682        assert_eq!(
1683            last_event,
1684            Some((vec![uuid_2.clone()], vec![uuid_2.clone()], vec![]).into())
1685        );
1686
1687        // load
1688        doc_ref_2.load(&mut doc.transact_mut());
1689        let last_event = event.swap(None);
1690        assert_eq!(
1691            last_event,
1692            Some(Arc::new((vec![], vec![], vec![uuid_2.clone()])))
1693        );
1694
1695        // apply from remote
1696        let doc2 = Doc::with_client_id(2);
1697        let event_c = event.clone();
1698        let _sub = doc2.observe_subdocs(move |_, e| {
1699            let added = e.added().map(|d| d.guid().clone()).collect();
1700            let removed = e.removed().map(|d| d.guid().clone()).collect();
1701            let loaded = e.loaded().map(|d| d.guid().clone()).collect();
1702
1703            event_c.store(Some(Arc::new((added, removed, loaded))));
1704        });
1705        let u = Update::decode_v1(
1706            &doc.transact()
1707                .encode_state_as_update_v1(&StateVector::default()),
1708        );
1709        doc2.transact_mut().apply_update(u.unwrap()).unwrap();
1710        let doc_ref_3 = {
1711            let array = doc2.get_or_insert_array("test");
1712            array
1713                .get(&doc2.transact(), 0)
1714                .unwrap()
1715                .cast::<Doc>()
1716                .unwrap()
1717        };
1718        assert!(!doc_ref_3.should_load());
1719        assert!(!doc_ref_3.auto_load());
1720        let uuid_3 = doc_ref_3.guid();
1721        let last_event = event.swap(None);
1722        assert_eq!(
1723            last_event,
1724            Some(Arc::new((vec![uuid_3.clone()], vec![], vec![])))
1725        );
1726
1727        // load
1728        doc_ref_3.load(&mut doc2.transact_mut());
1729        assert!(doc_ref_3.should_load());
1730        let last_event = event.swap(None);
1731        assert_eq!(
1732            last_event,
1733            Some(Arc::new((vec![], vec![], vec![uuid_3.clone()])))
1734        );
1735    }
1736
1737    #[test]
1738    fn subdoc_auto_load_edge_cases() {
1739        let doc = Doc::with_client_id(1);
1740        let array = doc.get_or_insert_array("test");
1741        let subdoc_1 = Doc::with_options({
1742            let mut o = Options::default();
1743            o.auto_load = true;
1744            o
1745        });
1746
1747        let event = Arc::new(ArcSwapOption::default());
1748        let event_c = event.clone();
1749        let _sub = doc.observe_subdocs(move |_, e| {
1750            let added = e.added().map(|d| d.guid().clone()).collect();
1751            let removed = e.removed().map(|d| d.guid().clone()).collect();
1752            let loaded = e.loaded().map(|d| d.guid().clone()).collect();
1753
1754            event_c.store(Some(Arc::new((added, removed, loaded))));
1755        });
1756
1757        let subdoc_1 = {
1758            let mut txn = doc.transact_mut();
1759            array.insert(&mut txn, 0, subdoc_1)
1760        };
1761        assert!(subdoc_1.should_load());
1762        assert!(subdoc_1.auto_load());
1763
1764        let uuid_1 = subdoc_1.guid();
1765        let last_event = event.swap(None);
1766        assert_eq!(
1767            last_event,
1768            Some(Arc::new((
1769                vec![uuid_1.clone()],
1770                vec![],
1771                vec![uuid_1.clone()]
1772            )))
1773        );
1774
1775        // destroy and check whether lastEvent adds it again to added (it shouldn't)
1776        subdoc_1.destroy(Some(&mut doc.transact_mut()));
1777
1778        let subdoc_2 = array
1779            .get(&doc.transact(), 0)
1780            .unwrap()
1781            .cast::<Doc>()
1782            .unwrap();
1783        let uuid_2 = subdoc_2.guid();
1784        assert!(!Doc::ptr_eq(&subdoc_1, &subdoc_2));
1785
1786        let last_event = event.swap(None);
1787        assert_eq!(
1788            last_event,
1789            Some(Arc::new((
1790                vec![uuid_2.clone()],
1791                vec![uuid_2.clone()],
1792                vec![]
1793            )))
1794        );
1795
1796        subdoc_2.load(&mut doc.transact_mut());
1797        let last_event = event.swap(None);
1798        assert_eq!(
1799            last_event,
1800            Some(Arc::new((vec![], vec![], vec![uuid_2.clone()])))
1801        );
1802
1803        // apply from remote
1804        let doc2 = Doc::with_client_id(2);
1805        let event_c = event.clone();
1806        let _sub = doc2.observe_subdocs(move |_, e| {
1807            let added = e.added().map(|d| d.guid()).collect();
1808            let removed = e.removed().map(|d| d.guid()).collect();
1809            let loaded = e.loaded().map(|d| d.guid()).collect();
1810
1811            event_c.store(Some(Arc::new((added, removed, loaded))));
1812        });
1813        let u = Update::decode_v1(
1814            &doc.transact()
1815                .encode_state_as_update_v1(&StateVector::default()),
1816        );
1817        doc2.transact_mut().apply_update(u.unwrap()).unwrap();
1818        let subdoc_3 = {
1819            let array = doc2.get_or_insert_array("test");
1820            array
1821                .get(&doc2.transact(), 0)
1822                .unwrap()
1823                .cast::<Doc>()
1824                .unwrap()
1825        };
1826        assert!(subdoc_1.should_load());
1827        assert!(subdoc_1.auto_load());
1828        let uuid_3 = subdoc_3.guid();
1829        let last_event = event.swap(None);
1830        assert_eq!(
1831            last_event,
1832            Some(Arc::new((
1833                vec![uuid_3.clone()],
1834                vec![],
1835                vec![uuid_3.clone()]
1836            )))
1837        );
1838    }
1839
1840    #[test]
1841    fn to_json() {
1842        let doc = Doc::new();
1843        let mut txn = doc.transact_mut();
1844        let text = txn.get_or_insert_text("text");
1845        let array = txn.get_or_insert_array("array");
1846        let map = txn.get_or_insert_map("map");
1847        let xml_fragment = txn.get_or_insert_xml_fragment("xml-fragment");
1848        let xml_element = xml_fragment.insert(&mut txn, 0, XmlElementPrelim::empty("xml-element"));
1849        let xml_text = xml_fragment.insert(&mut txn, 0, XmlTextPrelim::new(""));
1850
1851        text.push(&mut txn, "hello");
1852        xml_text.push(&mut txn, "world");
1853        xml_fragment.insert(&mut txn, 0, XmlElementPrelim::empty("div"));
1854        xml_element.insert(&mut txn, 0, XmlElementPrelim::empty("body"));
1855        array.insert_range(&mut txn, 0, [1, 2, 3]);
1856        map.insert(&mut txn, "key1", "value1");
1857
1858        // sub documents cannot use their parent's transaction
1859        let sub_doc = Doc::new();
1860        let sub_text = sub_doc.get_or_insert_text("sub-text");
1861        let sub_doc = map.insert(&mut txn, "sub-doc", sub_doc);
1862        let mut sub_txn = sub_doc.transact_mut();
1863        sub_text.push(&mut sub_txn, "sample");
1864
1865        let actual = doc.to_json(&txn);
1866        let expected = any!({
1867            "text": "hello",
1868            "array": [1,2,3],
1869            "map": {
1870                "key1": "value1",
1871                "sub-doc": {
1872                    "guid": sub_doc.guid().as_ref()
1873                }
1874            },
1875            "xml-fragment": "<div></div>world<xml-element><body></body></xml-element>",
1876        });
1877        assert_eq!(actual, expected);
1878    }
1879
1880    #[test]
1881    fn apply_snapshot_updates() {
1882        let update = {
1883            let doc = Doc::with_options(Options {
1884                client_id: ClientID::new(1),
1885                skip_gc: true,
1886                offset_kind: OffsetKind::Utf16,
1887                ..Options::default()
1888            });
1889            let txt = doc.get_or_insert_text("test");
1890            let mut txn = doc.transact_mut();
1891            txt.insert(&mut txn, 0, "hello");
1892
1893            let snap = txn.snapshot();
1894
1895            txt.insert(&mut txn, 5, " world");
1896
1897            let mut encoder = EncoderV1::new();
1898            txn.encode_state_from_snapshot(&snap, &mut encoder).unwrap();
1899            encoder.to_vec()
1900        };
1901
1902        let doc = Doc::with_client_id(1);
1903        let txt = doc.get_or_insert_text("test");
1904        let mut txn = doc.transact_mut();
1905        txn.apply_update(Update::decode_v1(&update).unwrap())
1906            .unwrap();
1907        let str = txt.get_string(&txn);
1908        assert_eq!(&str, "hello");
1909    }
1910
1911    #[test]
1912    fn out_of_order_updates() {
1913        let updates = Arc::new(Mutex::new(vec![]));
1914
1915        let d1 = Doc::new();
1916        let _sub = {
1917            let updates = updates.clone();
1918            d1.observe_update_v1(move |_, e| {
1919                let mut u = updates.lock().unwrap();
1920                u.push(Update::decode_v1(&e.update).unwrap());
1921            })
1922            .unwrap()
1923        };
1924
1925        let map = d1.get_or_insert_map("map");
1926        map.insert(&mut d1.transact_mut(), "a", 1); // U1: 'a' => 1
1927        map.insert(&mut d1.transact_mut(), "a", 1.1); // U2: 'a' => 1.1
1928        map.insert(&mut d1.transact_mut(), "b", 2); // U3: 'b' => 2
1929
1930        assert_eq!(map.to_json(&d1.transact()), any!({"a": 1.1, "b": 2}));
1931
1932        let d2 = Doc::new();
1933        let map = d2.get_or_insert_map("map");
1934
1935        {
1936            let mut updates = updates.lock().unwrap();
1937            let u3 = updates.pop().unwrap(); // 'b' => 2
1938            let u2 = updates.pop().unwrap(); // 'a' => 1.1
1939            let u1 = updates.pop().unwrap(); // 'a' => 1
1940            let mut txn = d2.transact_mut();
1941
1942            txn.apply_update(u1).unwrap(); // apply: 'a' => 1
1943            assert_eq!(map.to_json(&txn), any!({"a": 1}));
1944
1945            txn.apply_update(u3).unwrap(); // apply: 'b' => 2 (it's ok, we insert a skip for u2)
1946            assert_eq!(map.to_json(&txn), any!({"a": 1, "b": 2}));
1947
1948            txn.apply_update(u2).unwrap(); // apply: 'a' => 1.1
1949            assert_eq!(map.to_json(&txn), any!({"a": 1.1, "b": 2}));
1950        }
1951    }
1952
1953    #[test]
1954    fn encoding_buffer_overflow_errors() {
1955        assert_matches!(
1956            Update::decode_v1(&vec![
1957                0xe4, 0x9c, 0x10, 0x00, 0x05, 0xff, 0xff, 0x05, 0x00, 0x01, 0x00, 0x00, 0x00, 0x01,
1958                0x01, 0x00, 0x00, 0x00, 0xed, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0xfe, 0xb8, 0xc2,
1959                0xe9, 0xad, 0x87, 0xd9, 0x12, 0x00, 0x00, 0x01, 0x01, 0xff, 0xed, 0xf6,
1960            ]),
1961            Err(crate::encoding::read::Error::EndOfBuffer(_))
1962        );
1963
1964        assert_matches!(
1965            Update::decode_v2(&vec![
1966                0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00,
1967                0x16, 0x02, 0x00, 0x00, 0x01, 0xfd, 0xff, 0xff, 0xff, 0xff, 0x7f, 0x00, 0x00,
1968            ]),
1969            Err(crate::encoding::read::Error::EndOfBuffer(_))
1970        );
1971        assert_matches!(
1972            Update::decode_v2(&vec![
1973                0xe4, 0x95, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x01, 0x00, 0x01, 0x00, 0x00, 0x01,
1974                0x00, 0x00, 0xed, 0x01, 0xbe, 0x82, 0xe3, 0xc3, 0x1c, 0x01, 0x02, 0xe4, 0x95, 0x00,
1975                0x00, 0x01, 0x18, 0x00, 0x00, 0x01, 0x18, 0x00, 0x00, 0x01, 0x00, 0x01, 0xed, 0x00,
1976            ]),
1977            Err(crate::encoding::read::Error::InvalidVarInt)
1978        );
1979        assert_matches!(
1980            Update::decode_v2(&vec![
1981                0x8f, 0x01, 0x80, 0x00, 0x00, 0x00, 0x01, 0xaa, 0x01, 0x00, 0x01, 0x02, 0x00, 0x00,
1982                0x16, 0x02, 0x00, 0xe5, 0xc4, 0x43, 0x14, 0xe7, 0xa6, 0x8b, 0x93, 0xae, 0xb5, 0xfd,
1983                0x5d, 0xe8, 0x26, 0x9a, 0x8a, 0x59, 0x00, 0x31, 0xd5, 0x0f, 0x12, 0x01, 0x30, 0x00,
1984                0x00, 0x00,
1985            ]),
1986            Err(crate::encoding::read::Error::EndOfBuffer(_))
1987        );
1988        assert_matches!(
1989            Update::decode_v2(&vec![
1990                0x00, 0x01, 0x23, 0x00, 0x00, 0x00, 0x01, 0x02, 0x81, 0x00, 0x00, 0x10, 0x00, 0xc7,
1991                0xdc, 0x00, 0xc4, 0x7a, 0x80, 0x00, 0x41, 0xab, 0xea, 0xd6, 0x00, 0x01, 0x00, 0x00,
1992                0x01, 0x00, 0x00, 0x84, 0x00, 0x00, 0x10, 0xff, 0xc7, 0xdc, 0xff, 0x00, 0x00, 0x00,
1993            ]),
1994            Err(crate::encoding::read::Error::EndOfBuffer(_))
1995        );
1996    }
1997
1998    #[test]
1999    fn observe_after_transaction() {
2000        let d1 = Doc::with_client_id(1);
2001        let txt1 = d1.get_or_insert_text("text");
2002
2003        let e = Arc::new(ArcSwapOption::default());
2004        let e_copy = e.clone();
2005        d1.observe_after_transaction_with("key", move |txn| {
2006            e_copy.swap(Some(Arc::new((
2007                txn.before_state().clone(),
2008                txn.after_state().clone(),
2009                txn.delete_set.clone(),
2010            ))));
2011        })
2012        .unwrap();
2013
2014        txt1.insert(&mut d1.transact_mut(), 0, "hello world");
2015        let actual = e.swap(None);
2016        assert_eq!(
2017            actual,
2018            Some(Arc::new((
2019                StateVector::from_iter([(ClientID::new(1), 0)]),
2020                StateVector::from_iter([(ClientID::new(1), 11)]),
2021                IdSet::default()
2022            )))
2023        );
2024
2025        txt1.remove_range(&mut d1.transact_mut(), 2, 7);
2026        let actual = e.swap(None);
2027        assert_eq!(
2028            actual,
2029            Some(Arc::new((
2030                StateVector::from_iter([(ClientID::new(1), 11)]),
2031                StateVector::from_iter([(ClientID::new(1), 11)]),
2032                {
2033                    let mut ds = IdSet::new();
2034                    ds.insert(ID::new(ClientID::new(1), 2), 7);
2035                    ds
2036                }
2037            )))
2038        );
2039
2040        d1.unobserve_after_transaction("key").unwrap();
2041
2042        txt1.insert(&mut d1.transact_mut(), 4, " the door");
2043        let actual = e.swap(None);
2044        assert!(actual.is_none());
2045    }
2046
2047    fn init_test_data<const N: usize>(txn: &mut TransactionMut, data: [&str; N]) -> TextRef {
2048        let map = txn.get_or_insert_map("map");
2049        let txt = map.insert(txn, "text", TextPrelim::default());
2050        for ch in data {
2051            txt.insert(txn, 0, ch);
2052        }
2053        txt
2054    }
2055
2056    #[test]
2057    fn force_gc() {
2058        let doc = Doc::with_options(Options {
2059            client_id: ClientID::new(1),
2060            skip_gc: true,
2061            ..Default::default()
2062        });
2063        let map = doc.get_or_insert_map("map");
2064
2065        {
2066            // create some initial data
2067            let mut txn = doc.transact_mut();
2068            init_test_data(&mut txn, ["c", "b", "a"]);
2069
2070            // drop nested type
2071            map.remove(&mut txn, "text");
2072        }
2073
2074        // verify that skip_gc works and we have access to an original text content
2075        {
2076            let txn = doc.transact();
2077            let mut i = 1;
2078            for c in ["c", "b", "a"] {
2079                let block = txn
2080                    .store()
2081                    .blocks
2082                    .get_block(&ID::new(ClientID::new(1), i))
2083                    .unwrap()
2084                    .as_item()
2085                    .unwrap();
2086                assert!(block.is_deleted(), "`abc` should be marked as deleted");
2087                assert_eq!(&block.content, &ItemContent::String(c.into()));
2088                i += 1;
2089            }
2090        }
2091
2092        // force GC and check if original content is hard deleted
2093        doc.transact_mut().gc(None);
2094
2095        let txn = doc.transact();
2096        let block = txn
2097            .store()
2098            .blocks
2099            .get_block(&ID::new(ClientID::new(1), 1))
2100            .unwrap()
2101            .as_ref();
2102        assert_eq!(block.len(), 3, "GCed blocks should be squashed");
2103        assert!(block.is_deleted(), "`abc` should be deleted");
2104        assert_matches!(&block, &Block::GC(_));
2105    }
2106
2107    #[test]
2108    fn force_gc_with_delete_set() {
2109        let doc = Doc::with_options(Options {
2110            client_id: ClientID::new(1),
2111            skip_gc: true,
2112            ..Default::default()
2113        });
2114        let m0 = doc.get_or_insert_map("map");
2115        let s1 = {
2116            let mut tx = doc.transact_mut();
2117            let t1 = init_test_data(&mut tx, ["c", "b", "a"]); // <1#1..3>
2118            assert_eq!(t1.get_string(&tx), "abc");
2119            tx.snapshot()
2120        };
2121
2122        let s2 = {
2123            let mut tx = doc.transact_mut();
2124            let t2 = init_test_data(&mut tx, ["f", "e", "d"]); // <1#5..7>
2125            assert_eq!(t2.get_string(&tx), "def");
2126            tx.snapshot()
2127        };
2128
2129        let s3 = {
2130            let mut tx = doc.transact_mut();
2131            let t3 = init_test_data(&mut tx, ["i", "h", "g"]); // <1#9..11>
2132            assert_eq!(t3.get_string(&tx), "ghi");
2133            tx.snapshot()
2134        };
2135
2136        // restore data to s1
2137        {
2138            let doc_restored = restore_from_snapshot(&doc, &s1).unwrap();
2139            let txn = doc_restored.transact();
2140            let m0_restored = txn.get_map("map").unwrap();
2141            let txt = m0_restored
2142                .get(&txn, "text")
2143                .unwrap()
2144                .cast::<TextRef>()
2145                .unwrap();
2146            assert_eq!(txt.get_string(&txn), "abc");
2147        }
2148
2149        // verify that blocks 'abc' are not GCed and available
2150        {
2151            let txn = doc.transact();
2152            let mut i = 1;
2153            for c in ["c", "b", "a"] {
2154                let block = txn
2155                    .store()
2156                    .blocks
2157                    .get_block(&ID::new(ClientID::new(1), i))
2158                    .unwrap()
2159                    .as_item()
2160                    .unwrap();
2161                assert!(block.is_deleted(), "`abc` should be marked as deleted");
2162                assert_eq!(&block.content, &ItemContent::String(c.into()));
2163                i += 1;
2164            }
2165        }
2166
2167        // garbage collect anything below s2
2168        doc.transact_mut().gc(Some(&s2.delete_set));
2169
2170        // verify that we GC 'abc' blocks and compressed them
2171        let txn = doc.transact();
2172        let block = txn
2173            .store()
2174            .blocks
2175            .get_block(&ID::new(ClientID::new(1), 1))
2176            .unwrap()
2177            .as_ref();
2178        assert_eq!(
2179            block,
2180            &Block::GC(BlockRange::new(ID::new(ClientID::new(1), 1), 3)),
2181            "block should be GCed & compressed"
2182        );
2183
2184        // try to restore data to s1 again
2185        let doc_restored = restore_from_snapshot(&doc, &s1).unwrap();
2186        let txn = doc_restored.transact();
2187        let m0_restored = txn.get_map("map").unwrap();
2188        let txt = m0_restored.get(&txn, "text");
2189        assert!(
2190            txt.is_none(),
2191            "we restored snapshot s1, but it's content should be already GCed"
2192        );
2193
2194        // verify that blocks from s2 are still accessible
2195        {
2196            let doc_restored = restore_from_snapshot(&doc, &s2).unwrap();
2197            let txn = doc_restored.transact();
2198            let m0_restored = txn.get_map("map").unwrap();
2199            let txt = m0_restored
2200                .get(&txn, "text")
2201                .unwrap()
2202                .cast::<TextRef>()
2203                .unwrap();
2204            assert_eq!(txt.get_string(&txn), "def");
2205        }
2206    }
2207
2208    fn restore_from_snapshot(doc: &Doc, snapshot: &Snapshot) -> Result<Doc, Error> {
2209        let mut encoder = EncoderV1::new();
2210        doc.transact()
2211            .encode_state_from_snapshot(&snapshot, &mut encoder)?;
2212        let doc = Doc::new();
2213        doc.transact_mut()
2214            .apply_update(Update::decode_v1(&encoder.to_vec()).unwrap())
2215            .unwrap();
2216        Ok(doc)
2217    }
2218
2219    #[test]
2220    fn uuid_generation() {
2221        let guid = uuid_v4();
2222        let uuid = uuid::Uuid::parse_str(&guid).unwrap();
2223        assert_eq!(&*uuid.to_string(), &*guid);
2224    }
2225
2226    #[test]
2227    fn pending_delete_out_of_order() {
2228        // Test for bug fix: pending deletes should be recorded when the target client
2229        // doesn't exist in the block store yet
2230        let doc = Doc::new();
2231
2232        let (upd1, upd2) = {
2233            let doc2 = Doc::new();
2234            let mut tx = doc2.transact_mut();
2235            let text = tx.get_or_insert_text("example");
2236            text.insert(&mut tx, 0, "foo");
2237            let upd1 = tx.encode_update_v2();
2238            drop(tx);
2239
2240            let mut tx = doc2.transact_mut();
2241            let text = tx.get_or_insert_text("example");
2242            text.remove_range(&mut tx, 0, 1);
2243            let upd2 = tx.encode_update_v2();
2244            assert_eq!(text.get_string(&tx), "oo");
2245            drop(tx);
2246
2247            (upd1, upd2)
2248        };
2249
2250        // Apply delete BEFORE insert (out of order)
2251        let mut tx = doc.transact_mut();
2252        tx.apply_update(Update::decode_v2(&upd2).unwrap()).unwrap();
2253
2254        // Delete should be pending since the blocks don't exist yet
2255        assert!(tx.has_missing_updates(), "Delete should be pending");
2256
2257        // Apply insert
2258        tx.apply_update(Update::decode_v2(&upd1).unwrap()).unwrap();
2259
2260        // After insert arrives, pending delete should be auto-applied
2261        let text = tx.get_or_insert_text("example");
2262        assert_eq!(
2263            text.get_string(&tx),
2264            "oo",
2265            "Pending delete should have been applied"
2266        );
2267    }
2268}