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#[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
73macro_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 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 pub fn with_client_id(client_id: u64) -> Self {
184 Self::with_options(Options::with_client_id(ClientID::new(client_id)))
185 }
186
187 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 pub fn client_id(&self) -> ClientID {
209 self.store.options().client_id
210 }
211
212 pub fn guid(&self) -> Uuid {
217 self.store.options().guid.clone()
218 }
219
220 pub fn collection_id(&self) -> Option<Arc<str>> {
224 self.store.options().collection_id.clone()
225 }
226
227 pub fn skip_gc(&self) -> bool {
232 self.store.options().skip_gc
233 }
234
235 pub fn auto_load(&self) -> bool {
239 self.store.options().auto_load
240 }
241
242 pub fn should_load(&self) -> bool {
247 self.store.options().should_load
248 }
249
250 pub fn offset_kind(&self) -> OffsetKind {
252 self.store.options().offset_kind
253 }
254
255 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 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 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 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 observe_update_v1, observe_update_v1_with, unobserve_update_v1,
344 update_v1_events, FnMut(&TransactionMut, &UpdateEvent)
345 );
346
347 define_doc_observer!(
348 observe_update_v2, observe_update_v2_with, unobserve_update_v2,
353 update_v2_events, FnMut(&TransactionMut, &UpdateEvent)
354 );
355
356 define_doc_observer!(
357 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 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 observe_subdocs, observe_subdocs_with, unobserve_subdocs,
383 subdocs_events, FnMut(&TransactionMut, &SubdocsEvent)
384 );
385
386 define_doc_observer!(
387 observe_destroy, observe_destroy_with, unobserve_destroy,
390 destroy_events, FnMut(&TransactionMut, &Doc)
391 );
392
393 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 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 if let Some(mut events) = txn.store_mut().events.take() {
445 events.destroy_events.trigger(|cb| cb(&txn, self));
446 }
447 }
448
449 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#[derive(Debug, Clone, PartialEq, Eq)]
512pub struct Options {
513 pub client_id: ClientID,
518 pub guid: Uuid,
522 pub collection_id: Option<Arc<str>>,
527 pub offset_kind: OffsetKind,
531 pub skip_gc: bool,
535 pub auto_load: bool,
540 pub should_load: bool,
545
546 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, };
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; 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 _ => { }
631 }
632 }
633 }
634
635 Ok(options)
636 }
637}
638
639#[repr(u8)]
641#[derive(Debug, Clone, Copy, PartialEq, Eq)]
642pub enum OffsetKind {
643 Bytes,
645 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#[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 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 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 let d1 = Doc::new();
776 let txt = d1.get_or_insert_text("test");
777 let mut t1 = d1.transact_mut();
778 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 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 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 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 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); 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); }
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 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 let before_ref = before_state.clone();
978 let after_ref = after_state.clone();
979 let delete_ref = delete_set.clone();
980 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 text.insert(&mut txn, 0, "abc");
995 text.remove_range(&mut txn, 1, 2);
996 txn.commit();
997
998 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 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 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 txt1.push(&mut d1.transact_mut(), &c.to_string());
1082 }
1083
1084 assert_eq!(acc.lock().unwrap().as_str(), INPUT);
1085
1086 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.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 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 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 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 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 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 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 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); map.insert(&mut d1.transact_mut(), "a", 1.1); map.insert(&mut d1.transact_mut(), "b", 2); 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(); let u2 = updates.pop().unwrap(); let u1 = updates.pop().unwrap(); let mut txn = d2.transact_mut();
1941
1942 txn.apply_update(u1).unwrap(); assert_eq!(map.to_json(&txn), any!({"a": 1}));
1944
1945 txn.apply_update(u3).unwrap(); assert_eq!(map.to_json(&txn), any!({"a": 1, "b": 2}));
1947
1948 txn.apply_update(u2).unwrap(); 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 let mut txn = doc.transact_mut();
2068 init_test_data(&mut txn, ["c", "b", "a"]);
2069
2070 map.remove(&mut txn, "text");
2072 }
2073
2074 {
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 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"]); 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"]); 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"]); assert_eq!(t3.get_string(&tx), "ghi");
2133 tx.snapshot()
2134 };
2135
2136 {
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 {
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 doc.transact_mut().gc(Some(&s2.delete_set));
2169
2170 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 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 {
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 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 let mut tx = doc.transact_mut();
2252 tx.apply_update(Update::decode_v2(&upd2).unwrap()).unwrap();
2253
2254 assert!(tx.has_missing_updates(), "Delete should be pending");
2256
2257 tx.apply_update(Update::decode_v2(&upd1).unwrap()).unwrap();
2259
2260 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}