1use crate::block::{Block, EmbedPrelim, Item, ItemContent, ItemPosition, ItemPtr, Prelim, Unused};
2use crate::transaction::TransactionMut;
3use crate::types::{
4 AsPrelim, Attrs, Branch, BranchPtr, DefaultPrelim, Delta, Out, Path, RootRef, SharedRef,
5 TypePtr, TypeRef,
6};
7use crate::utils::OptionExt;
8use crate::*;
9use std::cell::UnsafeCell;
10use std::collections::HashMap;
11use std::convert::{TryFrom, TryInto};
12use std::fmt::Formatter;
13use std::ops::{Deref, DerefMut};
14
15#[repr(transparent)]
90#[derive(Debug, Clone)]
91pub struct TextRef(BranchPtr);
92
93impl RootRef for TextRef {
94 fn type_ref() -> TypeRef {
95 TypeRef::Text
96 }
97}
98impl SharedRef for TextRef {}
99impl Text for TextRef {}
100impl IndexedSequence for TextRef {}
101#[cfg(feature = "weak")]
102impl crate::Quotable for TextRef {}
103
104impl AsRef<XmlTextRef> for TextRef {
105 #[inline]
106 fn as_ref(&self) -> &XmlTextRef {
107 unsafe { std::mem::transmute(self) }
108 }
109}
110
111impl DeepObservable for TextRef {}
112impl Observable for TextRef {
113 type Event = TextEvent;
114}
115
116impl GetString for TextRef {
117 fn get_string<T: ReadTxn>(&self, _txn: &T) -> String {
121 let mut start = self.0.start;
122 let mut s = String::new();
123 while let Some(item) = start.as_deref() {
124 if !item.is_deleted() {
125 if let ItemContent::String(item_string) = &item.content {
126 s.push_str(item_string);
127 }
128 }
129 start = item.right.clone();
130 }
131 s
132 }
133}
134
135impl TryFrom<ItemPtr> for TextRef {
136 type Error = ItemPtr;
137
138 fn try_from(value: ItemPtr) -> Result<Self, Self::Error> {
139 if let Some(branch) = value.clone().as_branch() {
140 Ok(TextRef::from(branch))
141 } else {
142 Err(value)
143 }
144 }
145}
146
147impl TryFrom<Out> for TextRef {
148 type Error = Out;
149
150 fn try_from(value: Out) -> Result<Self, Self::Error> {
151 match value {
152 Out::YText(value) => Ok(value),
153 other => Err(other),
154 }
155 }
156}
157
158pub trait Text: AsRef<Branch> + Sized {
159 fn len<T: ReadTxn>(&self, _txn: &T) -> u32 {
161 self.as_ref().content_len
162 }
163
164 fn insert(&self, txn: &mut TransactionMut, index: u32, chunk: &str) {
213 if chunk.is_empty() {
214 return;
215 }
216 let this = BranchPtr::from(self.as_ref());
217 if let Some(mut pos) = find_position(this, txn, index) {
218 let value = crate::block::PrelimString(chunk.into());
219 while let Some(right) = pos.right.as_ref() {
220 if right.is_deleted() {
221 pos.forward();
223 } else {
224 break;
225 }
226 }
227 txn.create_item(&pos, value, None);
228 } else {
229 panic!("The type or the position doesn't exist!");
230 }
231 }
232
233 fn apply_delta<D, P>(&self, txn: &mut TransactionMut, delta: D)
234 where
235 D: IntoIterator<Item = Delta<P>>,
236 P: Prelim,
237 {
238 let branch = BranchPtr::from(self.as_ref());
239 let mut pos = ItemPosition {
240 parent: TypePtr::Branch(branch),
241 left: None,
242 right: branch.start,
243 index: 0,
244 current_attrs: Some(Box::new(Attrs::new())),
245 };
246 for delta in delta {
247 match delta {
248 Delta::Inserted(value, attrs) => {
249 let attrs: Attrs = match attrs {
250 None => Attrs::new(),
251 Some(attrs) => *attrs,
252 };
253 insert(branch, txn, &mut pos, DeltaChunk(value), attrs);
254 }
255 Delta::Deleted(len) => remove(txn, &mut pos, len),
256 Delta::Retain(len, attrs) => {
257 let attrs: Attrs = match attrs {
258 None => Attrs::new(),
259 Some(attrs) => *attrs,
260 };
261 insert_format(branch, txn, &mut pos, len, attrs);
262 }
263 }
264 }
265 }
266
267 fn insert_with_attributes(
276 &self,
277 txn: &mut TransactionMut,
278 index: u32,
279 chunk: &str,
280 attributes: Attrs,
281 ) {
282 if chunk.is_empty() {
283 return;
284 }
285 let this = BranchPtr::from(self.as_ref());
286 if let Some(mut pos) = find_position(this, txn, index) {
287 let value = block::PrelimString(chunk.into());
288 insert(this, txn, &mut pos, value, attributes);
289 } else {
290 panic!("The type or the position doesn't exist!");
291 }
292 }
293
294 fn insert_embed<V>(&self, txn: &mut TransactionMut, index: u32, content: V) -> V::Return
302 where
303 V: Into<EmbedPrelim<V>> + Prelim,
304 {
305 let this = BranchPtr::from(self.as_ref());
306 if let Some(pos) = find_position(this, txn, index) {
307 let ptr = txn
308 .create_item(&pos, content.into(), None)
309 .expect("cannot insert empty value");
310 if let Ok(integrated) = ptr.try_into() {
311 integrated
312 } else {
313 panic!("Defect: embedded return type doesn't match.")
314 }
315 } else {
316 panic!("The type or the position doesn't exist!");
317 }
318 }
319
320 fn insert_embed_with_attributes<V>(
329 &self,
330 txn: &mut TransactionMut,
331 index: u32,
332 embed: V,
333 attributes: Attrs,
334 ) -> V::Return
335 where
336 V: Into<EmbedPrelim<V>> + Prelim,
337 {
338 let this = BranchPtr::from(self.as_ref());
339 if let Some(mut pos) = find_position(this, txn, index) {
340 let item = insert(this, txn, &mut pos, embed.into(), attributes)
341 .expect("cannot insert empty value");
342 if let Ok(integrated) = item.try_into() {
343 integrated
344 } else {
345 panic!("Defect: unexpected returned integrated type")
346 }
347 } else {
348 panic!("The type or the position doesn't exist!");
349 }
350 }
351
352 fn push(&self, txn: &mut TransactionMut, chunk: &str) {
354 let idx = self.len(txn);
355 self.insert(txn, idx, chunk)
356 }
357
358 fn remove_range(&self, txn: &mut TransactionMut, index: u32, len: u32) {
362 let this = BranchPtr::from(self.as_ref());
363 if let Some(mut pos) = find_position(this, txn, index) {
364 remove(txn, &mut pos, len)
365 } else {
366 panic!("The type or the position doesn't exist!");
367 }
368 }
369
370 fn format(&self, txn: &mut TransactionMut, index: u32, len: u32, attributes: Attrs) {
373 let this = BranchPtr::from(self.as_ref());
374 if let Some(mut pos) = find_position(this, txn, index) {
375 insert_format(this, txn, &mut pos, len, attributes)
376 } else {
377 panic!("Index {} is outside of the range.", index);
378 }
379 }
380
381 fn diff<T, D, F>(&self, _txn: &T, compute_ychange: F) -> Vec<Diff<D>>
421 where
422 T: ReadTxn,
423 F: Fn(YChange) -> D,
424 {
425 let mut asm = DiffAssembler::new(compute_ychange);
426 asm.process(self.as_ref().start, None, None, None, None);
427 asm.finish()
428 }
429
430 fn diff_range<D, F>(
432 &self,
433 txn: &mut TransactionMut,
434 hi: Option<&Snapshot>,
435 lo: Option<&Snapshot>,
436 compute_ychange: F,
437 ) -> Vec<Diff<D>>
438 where
439 F: Fn(YChange) -> D,
440 {
441 if let Some(snapshot) = hi {
442 txn.split_by_snapshot(snapshot);
443 }
444 if let Some(snapshot) = lo {
445 txn.split_by_snapshot(snapshot);
446 }
447
448 let mut asm = DiffAssembler::new(compute_ychange);
449 asm.process(self.as_ref().start, hi, lo, None, None);
450 asm.finish()
451 }
452}
453
454impl From<BranchPtr> for TextRef {
455 fn from(inner: BranchPtr) -> Self {
456 TextRef(inner)
457 }
458}
459
460impl AsRef<Branch> for TextRef {
461 fn as_ref(&self) -> &Branch {
462 self.0.deref()
463 }
464}
465
466impl AsPrelim for TextRef {
467 type Prelim = DeltaPrelim;
468
469 fn as_prelim<T: ReadTxn>(&self, txn: &T) -> Self::Prelim {
470 let delta: Vec<Delta<In>> = self
471 .diff(txn, YChange::identity)
472 .into_iter()
473 .map(|diff| Delta::Inserted(diff.insert.as_prelim(txn), diff.attributes))
474 .collect();
475 DeltaPrelim(delta)
476 }
477}
478
479impl DefaultPrelim for TextRef {
480 type Prelim = TextPrelim;
481
482 #[inline]
483 fn default_prelim() -> Self::Prelim {
484 TextPrelim::default()
485 }
486}
487
488impl Eq for TextRef {}
489impl PartialEq for TextRef {
490 fn eq(&self, other: &Self) -> bool {
491 self.0.id() == other.0.id()
492 }
493}
494
495struct DeltaChunk<P>(P);
496
497impl<P> Prelim for DeltaChunk<P>
498where
499 P: Prelim,
500{
501 type Return = Unused;
502
503 fn into_content(self, txn: &mut TransactionMut) -> (ItemContent, Option<Self>) {
504 let (content, rest) = self.0.into_content(txn);
505 match content {
506 ItemContent::Any(mut any) if any.len() == 1 => match any.pop().unwrap() {
507 Any::String(str) => (ItemContent::String(str.as_ref().into()), None),
508 other => (ItemContent::Embed(other), None),
509 },
510 other => (other, rest.map(DeltaChunk)),
511 }
512 }
513
514 fn integrate(self, txn: &mut TransactionMut, inner_ref: BranchPtr) {
515 self.0.integrate(txn, inner_ref)
516 }
517}
518
519struct DiffAssembler<D, F>
520where
521 F: Fn(YChange) -> D,
522{
523 ops: Vec<Diff<D>>,
524 buf: String,
525 curr_attrs: Attrs,
526 curr_ychange: Option<YChange>,
527 compute_ychange: F,
528}
529
530impl<T, F> DiffAssembler<T, F>
531where
532 F: Fn(YChange) -> T,
533{
534 fn new(compute_ychange: F) -> Self {
535 DiffAssembler {
536 ops: Vec::new(),
537 buf: String::new(),
538 curr_attrs: HashMap::new(),
539 curr_ychange: None,
540 compute_ychange,
541 }
542 }
543 fn pack_str(&mut self) {
544 if !self.buf.is_empty() {
545 let attrs = self.attrs_boxed();
546 let mut buf = std::mem::replace(&mut self.buf, String::new());
547 buf.shrink_to_fit();
548 let change = if let Some(ychange) = self.curr_ychange.take() {
549 Some((self.compute_ychange)(ychange))
550 } else {
551 None
552 };
553 let op = Diff::with_change(Out::Any(buf.into()), attrs, change);
554 self.ops.push(op);
555 }
556 }
557
558 fn finish(self) -> Vec<Diff<T>> {
559 self.ops
560 }
561
562 fn attrs_boxed(&mut self) -> Option<Box<Attrs>> {
563 if self.curr_attrs.is_empty() {
564 None
565 } else {
566 Some(Box::new(self.curr_attrs.clone()))
567 }
568 }
569 fn process(
570 &mut self,
571 mut n: Option<ItemPtr>,
572 hi: Option<&Snapshot>,
573 lo: Option<&Snapshot>,
574 start: Option<&StickyIndex>,
575 end: Option<&StickyIndex>,
576 ) {
577 fn seen(snapshot: Option<&Snapshot>, item: &Item) -> bool {
578 if let Some(s) = snapshot {
579 s.is_visible(&item.id)
580 } else {
581 !item.is_deleted()
582 }
583 }
584 let (start, start_assoc) = if let Some(index) = start {
585 (index.id(), index.assoc)
586 } else {
587 (None, Assoc::Before)
588 };
589 let (end, end_assoc) = if let Some(index) = end {
590 (index.id(), index.assoc)
591 } else {
592 (None, Assoc::After)
593 };
594
595 let mut start_offset: i32 = if start.is_none() { 0 } else { -1 };
596 'LOOP: while let Some(item) = n.as_deref() {
597 if let Some(start) = start {
598 if start_offset < 0 && item.contains(start) {
599 if start_assoc == Assoc::After {
600 if start.clock == item.id.clock + item.len() - 1 {
601 start_offset = 0;
602 n = item.right;
603 continue;
604 } else {
605 start_offset = start.clock as i32 - item.id.clock as i32 + 1;
606 }
607 } else {
608 start_offset = start.clock as i32 - item.id.clock as i32;
609 }
610 }
611 }
612 if let Some(end) = end {
613 if end_assoc == Assoc::Before && &item.id == end {
614 break;
615 }
616 }
617 if seen(hi, item) || (lo.is_some() && seen(lo, item)) {
618 match &item.content {
619 ItemContent::String(s) => {
620 if let Some(snapshot) = hi {
621 if !snapshot.is_visible(&item.id) {
622 self.pack_str();
623 self.curr_ychange =
624 Some(YChange::new(ChangeKind::Removed, item.id));
625 } else if let Some(snapshot) = lo {
626 if !snapshot.is_visible(&item.id) {
627 self.pack_str();
628 self.curr_ychange =
629 Some(YChange::new(ChangeKind::Added, item.id));
630 } else if self.curr_ychange.is_some() {
631 self.pack_str();
632 }
633 }
634 }
635 if start_offset > 0 {
636 let slice = &s.as_str()[start_offset as usize..];
637 self.buf.push_str(slice);
638 start_offset = 0;
639 } else {
640 match end {
641 Some(end) if item.contains(end) => {
642 let mut end_offset =
644 (item.id.clock + item.len - end.clock - 1) as usize;
645 if end_assoc == Assoc::Before {
646 end_offset -= 1;
647 }
648 let s = s.as_str();
649 let slice = &s[..(s.len() + end_offset)];
650 self.buf.push_str(slice);
651 self.pack_str();
652 break 'LOOP;
653 }
654 _ => {
655 if start_offset == 0 {
656 self.buf.push_str(s.as_str());
657 }
658 }
659 }
660 }
661 }
662 ItemContent::Type(_) | ItemContent::Embed(_) => {
663 self.pack_str();
664 if let Some(value) = item.content.get_first() {
665 let attrs = self.attrs_boxed();
666 self.ops.push(Diff::new(value, attrs));
667 }
668 }
669 ItemContent::Format(key, value) => {
670 if seen(hi, item) {
671 self.pack_str();
672 update_current_attributes(&mut self.curr_attrs, key, value.as_ref());
673 }
674 }
675 _ => {}
676 }
677 } else if let Some(end) = end {
678 if item.contains(end) {
679 break;
680 }
681 }
682 n = item.right;
683 }
684
685 self.pack_str();
686 }
687}
688
689pub(crate) fn diff_between<D, F>(
690 ptr: Option<ItemPtr>,
691 start: Option<&StickyIndex>,
692 end: Option<&StickyIndex>,
693 compute_ychange: F,
694) -> Vec<Diff<D>>
695where
696 F: Fn(YChange) -> D,
697{
698 let mut asm = DiffAssembler::new(compute_ychange);
699 asm.process(ptr, None, None, start, end);
700 asm.finish()
701}
702
703fn insert<P: Prelim>(
704 branch: BranchPtr,
705 txn: &mut TransactionMut,
706 pos: &mut ItemPosition,
707 value: P,
708 mut attributes: Attrs,
709) -> Option<ItemPtr> {
710 pos.unset_missing(&mut attributes);
711 minimize_attr_changes(pos, &attributes);
712 let negated_attrs = insert_attributes(branch, txn, pos, attributes);
713
714 let item = if let Some(item) = txn.create_item(&pos, value, None) {
715 pos.right = Some(item);
716 pos.forward();
717 Some(item)
718 } else {
719 None
720 };
721
722 insert_negated_attributes(branch, txn, pos, negated_attrs);
723 item
724}
725
726pub(crate) fn update_current_attributes(attrs: &mut Attrs, key: &str, value: &Any) {
727 if let Any::Null = value {
728 attrs.remove(key);
729 } else {
730 attrs.insert(key.into(), value.clone());
731 }
732}
733
734fn find_position(this: BranchPtr, txn: &mut TransactionMut, index: u32) -> Option<ItemPosition> {
735 let mut pos = {
736 ItemPosition {
737 parent: this.into(),
738 left: None,
739 right: this.start,
740 index: 0,
741 current_attrs: None,
742 }
743 };
744
745 let mut format_ptrs = HashMap::new();
746 let store = txn.store_mut();
747 let encoding = store.offset_kind;
748 let mut remaining = index;
749 while let Some(right) = pos.right {
750 if remaining == 0 {
751 break;
752 }
753
754 if !right.is_deleted() {
755 match &right.content {
756 ItemContent::Format(key, value) => {
757 if let Any::Null = value.as_ref() {
758 format_ptrs.remove(key);
759 } else {
760 format_ptrs.insert(key.clone(), pos.right.clone());
761 }
762 }
763 _ => {
764 let mut block_len = right.len();
765 let content_len = right.content_len(encoding);
766 if remaining < content_len {
767 let offset = if let ItemContent::String(str) = &right.content {
769 str.block_offset(remaining, encoding)
770 } else {
771 remaining
772 };
773 store
774 .blocks
775 .split_block(right, offset, OffsetKind::Utf16)
776 .unwrap();
777 block_len -= offset;
778 remaining = 0;
779 } else {
780 remaining -= content_len;
781 }
782 pos.index += block_len;
783 }
784 }
785 }
786 pos.left = pos.right.take();
787 pos.right = if let Some(item) = pos.left.as_deref() {
788 item.right
789 } else {
790 None
791 };
792 }
793
794 for (_, block_ptr) in format_ptrs {
795 if let Some(item) = block_ptr {
796 if let ItemContent::Format(key, value) = &item.content {
797 let attrs = pos.current_attrs.get_or_init();
798 update_current_attributes(attrs, key, value.as_ref());
799 }
800 }
801 }
802
803 Some(pos)
804}
805
806fn remove(txn: &mut TransactionMut, pos: &mut ItemPosition, len: u32) {
807 let encoding = txn.store().offset_kind;
808 let mut remaining = len;
809 let start = pos.right.clone();
810 let start_attrs = pos.current_attrs.clone();
811 while let Some(item) = pos.right.as_deref() {
812 if remaining == 0 {
813 break;
814 }
815
816 if !item.is_deleted() {
817 match &item.content {
818 ItemContent::Embed(_) | ItemContent::String(_) | ItemContent::Type(_) => {
819 let content_len = item.content_len(encoding);
820 let ptr = pos.right.unwrap();
821 if remaining < content_len {
822 let offset = if let ItemContent::String(s) = &item.content {
824 s.block_offset(remaining, encoding)
825 } else {
826 len
827 };
828 remaining = 0;
829 txn.store_mut()
830 .blocks
831 .split_block(ptr, offset, OffsetKind::Utf16);
832 } else {
833 remaining -= content_len;
834 };
835 txn.delete(ptr);
836 }
837 _ => {}
838 }
839 }
840
841 pos.forward();
842 }
843
844 if remaining > 0 {
845 panic!(
846 "Couldn't remove {} elements from an array. Only {} of them were successfully removed.",
847 len,
848 len - remaining
849 );
850 }
851
852 if let (Some(start), Some(start_attrs), Some(end_attrs)) =
853 (start, start_attrs, pos.current_attrs.as_mut())
854 {
855 clean_format_gap(
856 txn,
857 Some(start),
858 pos.right,
859 start_attrs.as_ref(),
860 end_attrs.as_mut(),
861 );
862 }
863}
864
865fn is_valid_target(item: ItemPtr) -> bool {
866 if item.is_deleted() {
867 true
868 } else if let ItemContent::Format(_, _) = &item.content {
869 true
870 } else {
871 false
872 }
873}
874
875fn insert_format(
876 this: BranchPtr,
877 txn: &mut TransactionMut,
878 pos: &mut ItemPosition,
879 mut len: u32,
880 attrs: Attrs,
881) {
882 minimize_attr_changes(pos, &attrs);
883 let mut negated_attrs = insert_attributes(this, txn, pos, attrs.clone()); let encoding = txn.store().offset_kind;
885 while let Some(right) = pos.right {
890 if !(len > 0 || (!negated_attrs.is_empty() && is_valid_target(right))) {
891 break;
892 }
893
894 if !right.is_deleted() {
895 match &right.content {
896 ItemContent::Format(key, value) => {
897 if let Some(v) = attrs.get(key) {
898 if v == value.as_ref() {
899 negated_attrs.remove(key);
900 } else {
901 negated_attrs.insert(key.clone(), *value.clone());
902 }
903 txn.delete(right);
904 }
905 }
906 ItemContent::String(s) => {
907 let content_len = right.content_len(encoding);
908 if len < content_len {
909 let offset = s.block_offset(len, encoding);
911 let new_right =
912 txn.store_mut()
913 .blocks
914 .split_block(right, offset, OffsetKind::Utf16);
915 pos.left = Some(right);
916 pos.right = new_right;
917 break;
918 }
919 len -= content_len;
920 }
921 _ => {
922 let content_len = right.len();
923 if len < content_len {
924 let new_right =
925 txn.store_mut()
926 .blocks
927 .split_block(right, len, OffsetKind::Utf16);
928 pos.left = Some(right);
929 pos.right = new_right;
930 break;
931 }
932 len -= content_len;
933 }
934 }
935 }
936
937 if !pos.forward() {
938 break;
939 }
940 }
941
942 insert_negated_attributes(this, txn, pos, negated_attrs);
943}
944
945fn minimize_attr_changes(pos: &mut ItemPosition, attrs: &Attrs) {
946 while let Some(i) = pos.right.as_deref() {
948 if !i.is_deleted() {
949 if let ItemContent::Format(k, v) = &i.content {
950 if let Some(v2) = attrs.get(k) {
951 if (v.as_ref()).eq(v2) {
952 pos.forward();
953 continue;
954 }
955 }
956 }
957
958 break;
959 } else {
960 pos.forward();
961 }
962 }
963}
964
965fn insert_attributes(
966 this: BranchPtr,
967 txn: &mut TransactionMut,
968 pos: &mut ItemPosition,
969 attrs: Attrs,
970) -> Attrs {
971 let mut negated_attrs = HashMap::with_capacity(attrs.len());
972 let mut store = txn.store_mut();
973 for (k, v) in attrs {
974 let current_value = pos
975 .current_attrs
976 .as_ref()
977 .and_then(|a| a.get(&k))
978 .unwrap_or(&Any::Null);
979 if &v != current_value {
980 negated_attrs.insert(k.clone(), current_value.clone());
982
983 let client_id = store.client_id;
984 let parent = this.into();
985 let item = Item::new(
986 ID::new(client_id, store.blocks.get_clock(&client_id)),
987 pos.left.clone(),
988 pos.left.map(|ptr| ptr.last_id()),
989 pos.right.clone(),
990 pos.right.map(|ptr| ptr.id().clone()),
991 parent,
992 None,
993 ItemContent::Format(k, v.into()),
994 )
995 .unwrap();
996 let item_ptr = txn.integrate_item(item, 0);
997 pos.right = item_ptr;
998 pos.forward();
999 store = txn.store_mut();
1000 }
1001 }
1002 negated_attrs
1003}
1004
1005fn insert_negated_attributes(
1006 this: BranchPtr,
1007 txn: &mut TransactionMut,
1008 pos: &mut ItemPosition,
1009 mut attrs: Attrs,
1010) {
1011 while let Some(item) = pos.right.as_deref() {
1012 if !item.is_deleted() {
1013 if let ItemContent::Format(key, value) = &item.content {
1014 if let Some(curr_val) = attrs.get(key) {
1015 if curr_val == value.as_ref() {
1016 attrs.remove(key);
1017 pos.forward();
1018 continue;
1019 }
1020 }
1021 }
1022
1023 break;
1024 } else {
1025 pos.forward();
1026 }
1027 }
1028
1029 let mut store = txn.store_mut();
1030 for (k, v) in attrs {
1031 let client_id = store.client_id;
1032 let parent = this.into();
1033 let item = Item::new(
1034 ID::new(client_id, store.blocks.get_clock(&client_id)),
1035 pos.left.clone(),
1036 pos.left.map(|ptr| ptr.last_id()),
1037 pos.right.clone(),
1038 pos.right.map(|ptr| ptr.id().clone()),
1039 parent,
1040 None,
1041 ItemContent::Format(k, v.into()),
1042 )
1043 .unwrap();
1044 let item_ptr = txn.integrate_item(item, 0);
1045 pos.right = item_ptr;
1046 pos.forward();
1047 store = txn.store_mut();
1048 }
1049}
1050
1051fn clean_format_gap(
1052 txn: &mut TransactionMut,
1053 mut start: Option<ItemPtr>,
1054 mut end: Option<ItemPtr>,
1055 start_attrs: &Attrs,
1056 end_attrs: &mut Attrs,
1057) -> u32 {
1058 while let Some(item) = end.as_deref() {
1059 match &item.content {
1060 ItemContent::String(_) | ItemContent::Embed(_) => break,
1061 ItemContent::Format(key, value) if !item.is_deleted() => {
1062 update_current_attributes(end_attrs, key.as_ref(), value);
1063 }
1064 _ => {}
1065 }
1066 end = item.right.clone();
1067 }
1068
1069 let mut cleanups = 0;
1070 while start != end {
1071 if let Some(item) = start.as_deref() {
1072 let right = item.right.clone();
1073 if !item.is_deleted() {
1074 if let ItemContent::Format(key, value) = &item.content {
1075 let e = end_attrs.get(key).unwrap_or(&Any::Null);
1076 let s = start_attrs.get(key).unwrap_or(&Any::Null);
1077 if e != value.as_ref() || s == value.as_ref() {
1078 txn.delete(start.unwrap());
1079 cleanups += 1;
1080 }
1081 }
1082 }
1083 start = right;
1084 } else {
1085 break;
1086 }
1087 }
1088 cleanups
1089}
1090
1091#[derive(Debug, PartialEq)]
1096pub struct Diff<T> {
1097 pub insert: Out,
1100
1101 pub attributes: Option<Box<Attrs>>,
1103
1104 pub ychange: Option<T>,
1106}
1107
1108impl<T> Diff<T> {
1109 pub fn new(insert: Out, attributes: Option<Box<Attrs>>) -> Self {
1110 Self::with_change(insert, attributes, None)
1111 }
1112
1113 pub fn with_change(insert: Out, attributes: Option<Box<Attrs>>, ychange: Option<T>) -> Self {
1114 Diff {
1115 insert,
1116 attributes,
1117 ychange,
1118 }
1119 }
1120}
1121
1122impl<T> From<Diff<T>> for Delta {
1123 #[inline]
1124 fn from(value: Diff<T>) -> Self {
1125 Delta::Inserted(value.insert, value.attributes)
1126 }
1127}
1128
1129#[repr(transparent)]
1130#[derive(Debug, Clone, PartialEq, Default)]
1131pub struct DeltaPrelim(Vec<Delta<In>>);
1132
1133impl Deref for DeltaPrelim {
1134 type Target = [Delta<In>];
1135
1136 #[inline]
1137 fn deref(&self) -> &Self::Target {
1138 &self.0
1139 }
1140}
1141
1142impl Prelim for DeltaPrelim {
1143 type Return = TextRef;
1144
1145 fn into_content(self, _txn: &mut TransactionMut) -> (ItemContent, Option<Self>) {
1146 (ItemContent::Type(Branch::new(TypeRef::Text)), Some(self))
1147 }
1148
1149 fn integrate(self, txn: &mut TransactionMut, inner_ref: BranchPtr) {
1150 let text_ref = TextRef::from(inner_ref);
1151 text_ref.apply_delta(txn, self.0);
1152 }
1153}
1154
1155impl From<TextPrelim> for DeltaPrelim {
1156 fn from(value: TextPrelim) -> Self {
1157 DeltaPrelim(vec![Delta::Inserted(
1158 In::Any(Any::String(value.0.into())),
1159 None,
1160 )])
1161 }
1162}
1163
1164impl<T> std::fmt::Display for Diff<T> {
1165 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
1166 write!(f, "{{ insert: '{}'", self.insert)?;
1167 if let Some(attrs) = self.attributes.as_ref() {
1168 write!(f, ", attributes: {{")?;
1169 let mut i = attrs.iter();
1170 if let Some((k, v)) = i.next() {
1171 write!(f, " {}={}", k, v)?;
1172 }
1173 for (k, v) in i {
1174 write!(f, ", {}={}", k, v)?;
1175 }
1176 write!(f, " }}")?;
1177 }
1178 write!(f, " }}")
1179 }
1180}
1181
1182#[derive(Debug, Clone, PartialEq)]
1183pub struct YChange {
1184 pub kind: ChangeKind,
1185 pub id: ID,
1186}
1187
1188impl YChange {
1189 pub fn new(kind: ChangeKind, id: ID) -> Self {
1190 YChange { kind, id }
1191 }
1192
1193 #[inline]
1194 pub fn identity(change: YChange) -> YChange {
1195 change
1196 }
1197}
1198
1199#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1200pub enum ChangeKind {
1201 Added,
1202 Removed,
1203}
1204
1205pub struct TextEvent {
1207 pub(crate) current_target: BranchPtr,
1208 target: TextRef,
1209 delta: UnsafeCell<Option<Vec<Delta>>>,
1210}
1211
1212impl TextEvent {
1213 pub(crate) fn new(branch_ref: BranchPtr) -> Self {
1214 let current_target = branch_ref.clone();
1215 let target = TextRef::from(branch_ref);
1216 TextEvent {
1217 target,
1218 current_target,
1219 delta: UnsafeCell::new(None),
1220 }
1221 }
1222
1223 pub fn target(&self) -> &TextRef {
1225 &self.target
1226 }
1227
1228 pub fn path(&self) -> Path {
1230 Branch::path(self.current_target, self.target.0)
1231 }
1232
1233 pub fn delta(&self, txn: &TransactionMut) -> &[Delta] {
1236 let delta = unsafe { self.delta.get().as_mut().unwrap() };
1237 delta
1238 .get_or_insert_with(|| Self::get_delta(self.target.0, txn))
1239 .as_slice()
1240 }
1241
1242 pub(crate) fn get_delta(target: BranchPtr, txn: &TransactionMut) -> Vec<Delta> {
1243 #[derive(Debug, Clone, Copy, Eq, PartialEq)]
1244 enum Action {
1245 Insert,
1246 Retain,
1247 Delete,
1248 }
1249
1250 #[derive(Debug, Default)]
1251 struct DeltaAssembler {
1252 action: Option<Action>,
1253 insert: Option<Out>,
1254 insert_string: Option<String>,
1255 retain: u32,
1256 delete: u32,
1257 attrs: Attrs,
1258 current_attrs: Attrs,
1259 delta: Vec<Delta>,
1260 }
1261
1262 impl DeltaAssembler {
1263 fn add_op(&mut self) {
1264 match self.action.take() {
1265 None => {}
1266 Some(Action::Delete) => {
1267 let len = self.delete;
1268 self.delete = 0;
1269 self.delta.push(Delta::Deleted(len))
1270 }
1271 Some(Action::Insert) => {
1272 let value = if let Some(str) = self.insert.take() {
1273 str
1274 } else {
1275 let value = self.insert_string.take().unwrap();
1276 Any::from(value).into()
1277 };
1278 let attrs = if self.current_attrs.is_empty() {
1279 None
1280 } else {
1281 Some(Box::new(self.current_attrs.clone()))
1282 };
1283 self.delta.push(Delta::Inserted(value, attrs))
1284 }
1285 Some(Action::Retain) => {
1286 let len = self.retain;
1287 self.retain = 0;
1288 let attrs = if self.attrs.is_empty() {
1289 None
1290 } else {
1291 Some(Box::new(self.attrs.clone()))
1292 };
1293 self.delta.push(Delta::Retain(len, attrs));
1294 }
1295 }
1296 }
1297
1298 fn finish(mut self) -> Vec<Delta> {
1299 while let Some(last) = self.delta.pop() {
1300 match last {
1301 Delta::Retain(_, None) => {
1302 }
1304 other => {
1305 self.delta.push(other);
1306 return self.delta;
1307 }
1308 }
1309 }
1310 self.delta
1311 }
1312 }
1313
1314 let encoding = txn.store().offset_kind;
1315 let mut old_attrs = HashMap::new();
1316 let mut asm = DeltaAssembler::default();
1317 let mut current = target.start;
1318
1319 while let Some(item) = current.as_deref() {
1320 match &item.content {
1321 ItemContent::Type(_) | ItemContent::Embed(_) => {
1322 if txn.has_added(&item.id) {
1323 if !txn.has_deleted(&item.id) {
1324 asm.add_op();
1325 asm.action = Some(Action::Insert);
1326 asm.insert = item.content.get_last();
1327 asm.add_op();
1328 }
1329 } else if txn.has_deleted(&item.id) {
1330 if asm.action != Some(Action::Delete) {
1331 asm.add_op();
1332 asm.action = Some(Action::Delete);
1333 }
1334 asm.delete += 1;
1335 } else if !item.is_deleted() {
1336 if asm.action != Some(Action::Retain) {
1337 asm.add_op();
1338 asm.action = Some(Action::Retain);
1339 }
1340 asm.retain += 1;
1341 }
1342 }
1343 ItemContent::String(s) => {
1344 if txn.has_added(&item.id) {
1345 if !txn.has_deleted(&item.id) {
1346 if asm.action != Some(Action::Insert) {
1347 asm.add_op();
1348 asm.action = Some(Action::Insert);
1349 }
1350 let buf = asm.insert_string.get_or_insert_with(String::default);
1351 buf.push_str(s.as_str());
1352 }
1353 } else if txn.has_deleted(&item.id) {
1354 if asm.action != Some(Action::Delete) {
1355 asm.add_op();
1356 asm.action = Some(Action::Delete);
1357 }
1358 let content_len = item.content_len(encoding);
1359 asm.delete += content_len;
1360 } else if !item.is_deleted() {
1361 if asm.action != Some(Action::Retain) {
1362 asm.add_op();
1363 asm.action = Some(Action::Retain);
1364 }
1365 asm.retain += item.content_len(encoding);
1366 }
1367 }
1368 ItemContent::Format(key, value) => {
1369 if txn.has_added(&item.id) {
1370 if !txn.has_deleted(&item.id) {
1371 let current_val = asm.current_attrs.get(key);
1372 if current_val != Some(value) {
1373 if asm.action == Some(Action::Retain) {
1374 asm.add_op();
1375 }
1376 match old_attrs.get(key) {
1377 None if value.as_ref() == &Any::Null => {
1378 asm.attrs.remove(key);
1379 }
1380 Some(v) if v == value => {
1381 asm.attrs.remove(key);
1382 }
1383 _ => {
1384 asm.attrs.insert(key.clone(), *value.clone());
1385 }
1386 }
1387 } else {
1388 }
1390 }
1391 } else if txn.has_deleted(&item.id) {
1392 old_attrs.insert(key.clone(), value.clone());
1393 let current_val = asm.current_attrs.get(key).unwrap_or(&Any::Null);
1394 if current_val != value.as_ref() {
1395 let curr_val_clone = current_val.clone();
1396 if asm.action == Some(Action::Retain) {
1397 asm.add_op();
1398 }
1399 asm.attrs.insert(key.clone(), curr_val_clone);
1400 }
1401 } else if !item.is_deleted() {
1402 old_attrs.insert(key.clone(), value.clone());
1403 let attr = asm.attrs.get(key);
1404 if let Some(attr) = attr {
1405 if attr != value.as_ref() {
1406 if asm.action == Some(Action::Retain) {
1407 asm.add_op();
1408 }
1409 if value.as_ref() == &Any::Null {
1410 asm.attrs.remove(key);
1411 } else {
1412 asm.attrs.insert(key.clone(), *value.clone());
1413 }
1414 } else {
1415 }
1417 }
1418 }
1419
1420 if !item.is_deleted() {
1421 if asm.action == Some(Action::Insert) {
1422 asm.add_op();
1423 }
1424 update_current_attributes(&mut asm.current_attrs, key, value.as_ref());
1425 }
1426 }
1427 _ => {}
1428 }
1429
1430 current = item.right;
1431 }
1432
1433 asm.add_op();
1434 asm.finish()
1435 }
1436}
1437
1438#[repr(transparent)]
1441#[derive(Debug, Clone, PartialEq, Eq, Hash, Default)]
1442pub struct TextPrelim(String);
1443
1444impl TextPrelim {
1445 #[inline]
1446 pub fn new<S: Into<String>>(value: S) -> Self {
1447 TextPrelim(value.into())
1448 }
1449}
1450
1451impl Deref for TextPrelim {
1452 type Target = String;
1453
1454 #[inline]
1455 fn deref(&self) -> &Self::Target {
1456 &self.0
1457 }
1458}
1459
1460impl DerefMut for TextPrelim {
1461 #[inline]
1462 fn deref_mut(&mut self) -> &mut Self::Target {
1463 &mut self.0
1464 }
1465}
1466
1467impl From<TextPrelim> for In {
1468 #[inline]
1469 fn from(value: TextPrelim) -> Self {
1470 In::Text(DeltaPrelim::from(value))
1471 }
1472}
1473
1474impl Prelim for TextPrelim {
1475 type Return = TextRef;
1476
1477 fn into_content(self, _txn: &mut TransactionMut) -> (ItemContent, Option<Self>) {
1478 let inner = Branch::new(TypeRef::Text);
1479 (ItemContent::Type(inner), Some(self))
1480 }
1481
1482 fn integrate(self, txn: &mut TransactionMut, inner_ref: BranchPtr) {
1483 if !self.0.is_empty() {
1484 let text = TextRef::from(inner_ref);
1485 text.push(txn, &self.0);
1486 }
1487 }
1488}
1489
1490impl Into<EmbedPrelim<TextPrelim>> for TextPrelim {
1491 #[inline]
1492 fn into(self) -> EmbedPrelim<TextPrelim> {
1493 EmbedPrelim::Shared(self)
1494 }
1495}
1496
1497#[cfg(test)]
1498mod test {
1499 use crate::block::ClientID;
1500 use crate::doc::{OffsetKind, Options};
1501 use crate::test_utils::{exchange_updates, run_scenario, RngExt};
1502 use crate::transaction::ReadTxn;
1503 use crate::types::text::{Attrs, ChangeKind, Delta, Diff, YChange};
1504 use crate::types::Out;
1505 use crate::updates::decoder::Decode;
1506 use crate::updates::encoder::{Encode, Encoder, EncoderV1};
1507 use crate::{
1508 any, Any, ArrayPrelim, Doc, GetString, Map, MapPrelim, MapRef, Observable, StateVector,
1509 Text, Transact, Update, WriteTxn, ID,
1510 };
1511 use arc_swap::ArcSwapOption;
1512 use fastrand::Rng;
1513 use std::collections::HashMap;
1514 use std::sync::atomic::{AtomicBool, Ordering};
1515 use std::sync::Arc;
1516 use std::time::Duration;
1517
1518 #[test]
1519 fn insert_empty_string() {
1520 let doc = Doc::new();
1521 let txt = doc.get_or_insert_text("test");
1522 let mut txn = doc.transact_mut();
1523
1524 assert_eq!(txt.get_string(&txn).as_str(), "");
1525
1526 txt.push(&mut txn, "");
1527 assert_eq!(txt.get_string(&txn).as_str(), "");
1528
1529 txt.push(&mut txn, "abc");
1530 txt.push(&mut txn, "");
1531 assert_eq!(txt.get_string(&txn).as_str(), "abc");
1532 }
1533
1534 #[test]
1535 fn append_single_character_blocks() {
1536 let doc = Doc::new();
1537 let txt = doc.get_or_insert_text("test");
1538 let mut txn = doc.transact_mut();
1539
1540 txt.insert(&mut txn, 0, "a");
1541 txt.insert(&mut txn, 1, "b");
1542 txt.insert(&mut txn, 2, "c");
1543
1544 assert_eq!(txt.get_string(&txn).as_str(), "abc");
1545 }
1546
1547 #[test]
1548 fn append_mutli_character_blocks() {
1549 let doc = Doc::new();
1550 let txt = doc.get_or_insert_text("test");
1551 let mut txn = doc.transact_mut();
1552
1553 txt.insert(&mut txn, 0, "hello");
1554 txt.insert(&mut txn, 5, " ");
1555 txt.insert(&mut txn, 6, "world");
1556
1557 assert_eq!(txt.get_string(&txn).as_str(), "hello world");
1558 }
1559
1560 #[test]
1561 fn prepend_single_character_blocks() {
1562 let doc = Doc::new();
1563 let txt = doc.get_or_insert_text("test");
1564 let mut txn = doc.transact_mut();
1565
1566 txt.insert(&mut txn, 0, "a");
1567 txt.insert(&mut txn, 0, "b");
1568 txt.insert(&mut txn, 0, "c");
1569
1570 assert_eq!(txt.get_string(&txn).as_str(), "cba");
1571 }
1572
1573 #[test]
1574 fn prepend_mutli_character_blocks() {
1575 let doc = Doc::new();
1576 let txt = doc.get_or_insert_text("test");
1577 let mut txn = doc.transact_mut();
1578
1579 txt.insert(&mut txn, 0, "hello");
1580 txt.insert(&mut txn, 0, " ");
1581 txt.insert(&mut txn, 0, "world");
1582
1583 assert_eq!(txt.get_string(&txn).as_str(), "world hello");
1584 }
1585
1586 #[test]
1587 fn insert_after_block() {
1588 let doc = Doc::new();
1589 let txt = doc.get_or_insert_text("test");
1590 let mut txn = doc.transact_mut();
1591
1592 txt.insert(&mut txn, 0, "hello");
1593 txt.insert(&mut txn, 5, " ");
1594 txt.insert(&mut txn, 6, "world");
1595 txt.insert(&mut txn, 6, "beautiful ");
1596
1597 assert_eq!(txt.get_string(&txn).as_str(), "hello beautiful world");
1598 }
1599
1600 #[test]
1601 fn insert_inside_of_block() {
1602 let doc = Doc::new();
1603 let txt = doc.get_or_insert_text("test");
1604 let mut txn = doc.transact_mut();
1605
1606 txt.insert(&mut txn, 0, "it was expected");
1607 txt.insert(&mut txn, 6, " not");
1608
1609 assert_eq!(txt.get_string(&txn).as_str(), "it was not expected");
1610 }
1611
1612 #[test]
1613 fn insert_concurrent_root() {
1614 let d1 = Doc::with_client_id(1);
1615 let txt1 = d1.get_or_insert_text("test");
1616 let mut t1 = d1.transact_mut();
1617
1618 txt1.insert(&mut t1, 0, "hello ");
1619
1620 let d2 = Doc::with_client_id(2);
1621 let txt2 = d2.get_or_insert_text("test");
1622 let mut t2 = d2.transact_mut();
1623
1624 txt2.insert(&mut t2, 0, "world");
1625
1626 let d1_sv = t1.state_vector().encode_v1();
1627 let d2_sv = t2.state_vector().encode_v1();
1628
1629 let u1 = t1.encode_diff_v1(&StateVector::decode_v1(&d2_sv).unwrap());
1630 let u2 = t2.encode_diff_v1(&StateVector::decode_v1(&d1_sv).unwrap());
1631
1632 t1.apply_update(Update::decode_v1(u2.as_slice()).unwrap())
1633 .unwrap();
1634 t2.apply_update(Update::decode_v1(u1.as_slice()).unwrap())
1635 .unwrap();
1636
1637 let a = txt1.get_string(&t1);
1638 let b = txt2.get_string(&t2);
1639
1640 assert_eq!(a, b);
1641 assert_eq!(a.as_str(), "hello world");
1642 }
1643
1644 #[test]
1645 fn insert_concurrent_in_the_middle() {
1646 let d1 = Doc::with_client_id(1);
1647 let txt1 = d1.get_or_insert_text("test");
1648 let mut t1 = d1.transact_mut();
1649
1650 txt1.insert(&mut t1, 0, "I expect that");
1651 assert_eq!(txt1.get_string(&t1).as_str(), "I expect that");
1652
1653 let d2 = Doc::with_client_id(2);
1654 let txt2 = d2.get_or_insert_text("test");
1655 let mut t2 = d2.transact_mut();
1656
1657 let d2_sv = t2.state_vector().encode_v1();
1658 let u1 = t1.encode_diff_v1(&StateVector::decode_v1(&d2_sv).unwrap());
1659 t2.apply_update(Update::decode_v1(u1.as_slice()).unwrap())
1660 .unwrap();
1661
1662 assert_eq!(txt2.get_string(&t2).as_str(), "I expect that");
1663
1664 txt2.insert(&mut t2, 1, " have");
1665 txt2.insert(&mut t2, 13, "ed");
1666 assert_eq!(txt2.get_string(&t2).as_str(), "I have expected that");
1667
1668 txt1.insert(&mut t1, 1, " didn't");
1669 assert_eq!(txt1.get_string(&t1).as_str(), "I didn't expect that");
1670
1671 let d2_sv = t2.state_vector().encode_v1();
1672 let d1_sv = t1.state_vector().encode_v1();
1673 let u1 = t1.encode_diff_v1(&StateVector::decode_v1(&d2_sv.as_slice()).unwrap());
1674 let u2 = t2.encode_diff_v1(&StateVector::decode_v1(&d1_sv.as_slice()).unwrap());
1675 t1.apply_update(Update::decode_v1(u2.as_slice()).unwrap())
1676 .unwrap();
1677 t2.apply_update(Update::decode_v1(u1.as_slice()).unwrap())
1678 .unwrap();
1679
1680 let a = txt1.get_string(&t1);
1681 let b = txt2.get_string(&t2);
1682
1683 assert_eq!(a, b);
1684 assert_eq!(a.as_str(), "I didn't have expected that");
1685 }
1686
1687 #[test]
1688 fn append_concurrent() {
1689 let d1 = Doc::with_client_id(1);
1690 let txt1 = d1.get_or_insert_text("test");
1691 let mut t1 = d1.transact_mut();
1692
1693 txt1.insert(&mut t1, 0, "aaa");
1694 assert_eq!(txt1.get_string(&t1).as_str(), "aaa");
1695
1696 let d2 = Doc::with_client_id(2);
1697 let txt2 = d2.get_or_insert_text("test");
1698 let mut t2 = d2.transact_mut();
1699
1700 let d2_sv = t2.state_vector().encode_v1();
1701 let u1 = t1.encode_diff_v1(&StateVector::decode_v1(&d2_sv.as_slice()).unwrap());
1702 t2.apply_update(Update::decode_v1(u1.as_slice()).unwrap())
1703 .unwrap();
1704
1705 assert_eq!(txt2.get_string(&t2).as_str(), "aaa");
1706
1707 txt2.insert(&mut t2, 3, "bbb");
1708 txt2.insert(&mut t2, 6, "bbb");
1709 assert_eq!(txt2.get_string(&t2).as_str(), "aaabbbbbb");
1710
1711 txt1.insert(&mut t1, 3, "aaa");
1712 assert_eq!(txt1.get_string(&t1).as_str(), "aaaaaa");
1713
1714 let d2_sv = t2.state_vector().encode_v1();
1715 let d1_sv = t1.state_vector().encode_v1();
1716 let u1 = t1.encode_diff_v1(&StateVector::decode_v1(&d2_sv.as_slice()).unwrap());
1717 let u2 = t2.encode_diff_v1(&StateVector::decode_v1(&d1_sv.as_slice()).unwrap());
1718
1719 t1.apply_update(Update::decode_v1(u2.as_slice()).unwrap())
1720 .unwrap();
1721 t2.apply_update(Update::decode_v1(u1.as_slice()).unwrap())
1722 .unwrap();
1723
1724 let a = txt1.get_string(&t1);
1725 let b = txt2.get_string(&t2);
1726
1727 assert_eq!(a.as_str(), "aaaaaabbbbbb");
1728 assert_eq!(a, b);
1729 }
1730
1731 #[test]
1732 fn delete_single_block_start() {
1733 let doc = Doc::new();
1734 let txt = doc.get_or_insert_text("test");
1735 let mut txn = doc.transact_mut();
1736
1737 txt.insert(&mut txn, 0, "bbb");
1738 txt.insert(&mut txn, 0, "aaa");
1739 txt.remove_range(&mut txn, 0, 3);
1740
1741 assert_eq!(txt.len(&txn), 3);
1742 assert_eq!(txt.get_string(&txn).as_str(), "bbb");
1743 }
1744
1745 #[test]
1746 fn delete_single_block_end() {
1747 let doc = Doc::new();
1748 let txt = doc.get_or_insert_text("test");
1749 let mut txn = doc.transact_mut();
1750
1751 txt.insert(&mut txn, 0, "bbb");
1752 txt.insert(&mut txn, 0, "aaa");
1753 txt.remove_range(&mut txn, 3, 3);
1754
1755 assert_eq!(txt.get_string(&txn).as_str(), "aaa");
1756 }
1757
1758 #[test]
1759 fn delete_multiple_whole_blocks() {
1760 let doc = Doc::new();
1761 let txt = doc.get_or_insert_text("test");
1762 let mut txn = doc.transact_mut();
1763
1764 txt.insert(&mut txn, 0, "a");
1765 txt.insert(&mut txn, 1, "b");
1766 txt.insert(&mut txn, 2, "c");
1767
1768 txt.remove_range(&mut txn, 1, 1);
1769 assert_eq!(txt.get_string(&txn).as_str(), "ac");
1770
1771 txt.remove_range(&mut txn, 1, 1);
1772 assert_eq!(txt.get_string(&txn).as_str(), "a");
1773
1774 txt.remove_range(&mut txn, 0, 1);
1775 assert_eq!(txt.get_string(&txn).as_str(), "");
1776 }
1777
1778 #[test]
1779 fn delete_slice_of_block() {
1780 let doc = Doc::new();
1781 let txt = doc.get_or_insert_text("test");
1782 let mut txn = doc.transact_mut();
1783
1784 txt.insert(&mut txn, 0, "abc");
1785 txt.remove_range(&mut txn, 1, 1);
1786
1787 assert_eq!(txt.get_string(&txn).as_str(), "ac");
1788 }
1789
1790 #[test]
1791 fn delete_multiple_blocks_with_slicing() {
1792 let doc = Doc::new();
1793 let txt = doc.get_or_insert_text("test");
1794 let mut txn = doc.transact_mut();
1795
1796 txt.insert(&mut txn, 0, "hello ");
1797 txt.insert(&mut txn, 6, "beautiful");
1798 txt.insert(&mut txn, 15, " world");
1799
1800 txt.remove_range(&mut txn, 5, 11);
1801 assert_eq!(txt.get_string(&txn).as_str(), "helloworld");
1802 }
1803
1804 #[test]
1805 fn insert_after_delete() {
1806 let doc = Doc::new();
1807 let txt = doc.get_or_insert_text("test");
1808 let mut txn = doc.transact_mut();
1809
1810 txt.insert(&mut txn, 0, "hello ");
1811 txt.remove_range(&mut txn, 0, 5);
1812 txt.insert(&mut txn, 1, "world");
1813
1814 assert_eq!(txt.get_string(&txn).as_str(), " world");
1815 }
1816
1817 #[test]
1818 fn concurrent_insert_delete() {
1819 let d1 = Doc::with_client_id(1);
1820 let txt1 = d1.get_or_insert_text("test");
1821 let mut t1 = d1.transact_mut();
1822
1823 txt1.insert(&mut t1, 0, "hello world");
1824 assert_eq!(txt1.get_string(&t1).as_str(), "hello world");
1825
1826 let u1 = t1.encode_state_as_update_v1(&StateVector::default());
1827
1828 let d2 = Doc::with_client_id(2);
1829 let txt2 = d2.get_or_insert_text("test");
1830 let mut t2 = d2.transact_mut();
1831 t2.apply_update(Update::decode_v1(u1.as_slice()).unwrap())
1832 .unwrap();
1833 assert_eq!(txt2.get_string(&t2).as_str(), "hello world");
1834
1835 txt1.insert(&mut t1, 5, " beautiful");
1836 txt1.insert(&mut t1, 21, "!");
1837 txt1.remove_range(&mut t1, 0, 5);
1838 assert_eq!(txt1.get_string(&t1).as_str(), " beautiful world!");
1839
1840 txt2.remove_range(&mut t2, 5, 5);
1841 txt2.remove_range(&mut t2, 0, 1);
1842 txt2.insert(&mut t2, 0, "H");
1843 assert_eq!(txt2.get_string(&t2).as_str(), "Hellod");
1844
1845 let sv1 = t1.state_vector().encode_v1();
1846 let sv2 = t2.state_vector().encode_v1();
1847 let u1 = t1.encode_diff_v1(&StateVector::decode_v1(&sv2.as_slice()).unwrap());
1848 let u2 = t2.encode_diff_v1(&StateVector::decode_v1(&sv1.as_slice()).unwrap());
1849
1850 t1.apply_update(Update::decode_v1(u2.as_slice()).unwrap())
1851 .unwrap();
1852 t2.apply_update(Update::decode_v1(u1.as_slice()).unwrap())
1853 .unwrap();
1854
1855 let a = txt1.get_string(&t1);
1856 let b = txt2.get_string(&t2);
1857
1858 assert_eq!(a, b);
1859 assert_eq!(a, "H beautifuld!".to_owned());
1860 }
1861
1862 #[test]
1863 fn observer() {
1864 let doc = Doc::with_client_id(1);
1865 let txt = doc.get_or_insert_text("text");
1866 let delta = Arc::new(ArcSwapOption::default());
1867 let delta_c = delta.clone();
1868 let sub = txt.observe(move |txn, e| {
1869 delta_c.store(Some(Arc::new(e.delta(txn).to_vec())));
1870 });
1871
1872 txt.insert(&mut doc.transact_mut(), 0, "abcd"); assert_eq!(
1875 delta.load_full(),
1876 Some(Arc::new(vec![Delta::Inserted("abcd".into(), None)]))
1877 );
1878
1879 txt.remove_range(&mut doc.transact_mut(), 1, 2); assert_eq!(
1882 delta.load_full(),
1883 Some(Arc::new(vec![Delta::Retain(1, None), Delta::Deleted(2)]))
1884 );
1885
1886 let attrs = Attrs::from([("bold".into(), true.into())]);
1888 txt.insert_with_attributes(&mut doc.transact_mut(), 1, "e", attrs.clone()); assert_eq!(
1890 delta.load_full(),
1891 Some(Arc::new(vec![
1892 Delta::Retain(1, None),
1893 Delta::Inserted("e".into(), Some(Box::new(attrs)))
1894 ]))
1895 );
1896
1897 let attrs = Attrs::from([("bold".into(), Any::Null)]);
1899 txt.format(&mut doc.transact_mut(), 1, 1, attrs.clone()); assert_eq!(
1901 delta.swap(None),
1902 Some(Arc::new(vec![
1903 Delta::Retain(1, None),
1904 Delta::Retain(2, Some(Box::new(attrs)))
1905 ]))
1906 );
1907
1908 drop(sub);
1910 txt.insert(&mut doc.transact_mut(), 1, "fgh"); assert_eq!(delta.swap(None), None);
1912 }
1913
1914 #[test]
1915 fn insert_and_remove_event_changes() {
1916 let d1 = Doc::with_client_id(1);
1917 let txt = d1.get_or_insert_text("text");
1918 let delta = Arc::new(ArcSwapOption::default());
1919 let delta_c = delta.clone();
1920 let _sub = txt.observe(move |txn, e| delta_c.store(Some(Arc::new(e.delta(txn).to_vec()))));
1921
1922 {
1924 let mut txn = d1.transact_mut();
1925 txt.insert(&mut txn, 0, "abcd");
1926 }
1927 assert_eq!(
1928 delta.swap(None),
1929 Some(Arc::new(vec![Delta::Inserted("abcd".into(), None)]))
1930 );
1931
1932 {
1934 let mut txn = d1.transact_mut();
1935 txt.remove_range(&mut txn, 1, 2);
1936 }
1937 assert_eq!(
1938 delta.swap(None),
1939 Some(Arc::new(vec![Delta::Retain(1, None), Delta::Deleted(2)]))
1940 );
1941
1942 {
1944 let mut txn = d1.transact_mut();
1945 txt.insert(&mut txn, 1, "ef");
1946 }
1947 assert_eq!(
1948 delta.swap(None),
1949 Some(Arc::new(vec![
1950 Delta::Retain(1, None),
1951 Delta::Inserted("ef".into(), None)
1952 ]))
1953 );
1954
1955 let d2 = Doc::with_client_id(2);
1957 let txt = d2.get_or_insert_text("text");
1958 let delta_c = delta.clone();
1959 let _sub = txt.observe(move |txn, e| delta_c.store(Some(Arc::new(e.delta(txn).to_vec()))));
1960
1961 {
1962 let t1 = d1.transact_mut();
1963 let mut t2 = d2.transact_mut();
1964
1965 let sv = t2.state_vector();
1966 let mut encoder = EncoderV1::new();
1967 t1.encode_diff(&sv, &mut encoder);
1968 t2.apply_update(Update::decode_v1(encoder.to_vec().as_slice()).unwrap())
1969 .unwrap();
1970 }
1971
1972 assert_eq!(
1973 delta.swap(None),
1974 Some(Arc::new(vec![Delta::Inserted("aefd".into(), None)]))
1975 );
1976 }
1977
1978 fn text_transactions() -> [Box<dyn Fn(&mut Doc, &mut Rng)>; 2] {
1979 fn insert_text(doc: &mut Doc, rng: &mut Rng) {
1980 let ytext = doc.get_or_insert_text("text");
1981 let mut txn = doc.transact_mut();
1982 let pos = rng.between(0, ytext.len(&txn));
1983 let word = rng.random_string();
1984 ytext.insert(&mut txn, pos, word.as_str());
1985 }
1986
1987 fn delete_text(doc: &mut Doc, rng: &mut Rng) {
1988 let ytext = doc.get_or_insert_text("text");
1989 let mut txn = doc.transact_mut();
1990 let len = ytext.len(&txn);
1991 if len > 0 {
1992 let pos = rng.between(0, len - 1);
1993 let to_delete = rng.between(2, len - pos);
1994 ytext.remove_range(&mut txn, pos, to_delete);
1995 }
1996 }
1997
1998 [Box::new(insert_text), Box::new(delete_text)]
1999 }
2000
2001 fn fuzzy(iterations: usize) {
2002 run_scenario(0, &text_transactions(), 5, iterations)
2003 }
2004
2005 #[test]
2006 fn fuzzy_test_3() {
2007 fuzzy(3)
2008 }
2009
2010 #[test]
2011 fn basic_format() {
2012 let d1 = Doc::with_client_id(1);
2013 let txt1 = d1.get_or_insert_text("text");
2014
2015 let delta1 = Arc::new(ArcSwapOption::default());
2016 let delta_clone = delta1.clone();
2017 let _sub1 =
2018 txt1.observe(move |txn, e| delta_clone.store(Some(Arc::new(e.delta(txn).to_vec()))));
2019
2020 let d2 = Doc::with_client_id(2);
2021 let txt2 = d2.get_or_insert_text("text");
2022
2023 let delta2 = Arc::new(ArcSwapOption::default());
2024 let delta_clone = delta2.clone();
2025 let _sub2 =
2026 txt2.observe(move |txn, e| delta_clone.store(Some(Arc::new(e.delta(txn).to_vec()))));
2027
2028 let a: Attrs = HashMap::from([("bold".into(), Any::Bool(true))]);
2029
2030 {
2032 let mut txn = d1.transact_mut();
2033 txt1.insert_with_attributes(&mut txn, 0, "abc", a.clone());
2034 let update = txn.encode_update_v1();
2035 drop(txn);
2036
2037 let expected = Some(Arc::new(vec![Delta::Inserted(
2038 "abc".into(),
2039 Some(Box::new(a.clone())),
2040 )]));
2041
2042 assert_eq!(txt1.get_string(&d1.transact()), "abc".to_string());
2043 assert_eq!(
2044 txt1.diff(&d1.transact(), YChange::identity),
2045 vec![Diff::new("abc".into(), Some(Box::new(a.clone())))]
2046 );
2047 assert_eq!(delta1.swap(None), expected);
2048
2049 let mut txn = d2.transact_mut();
2050 txn.apply_update(Update::decode_v1(update.as_slice()).unwrap())
2051 .unwrap();
2052 drop(txn);
2053
2054 assert_eq!(txt2.get_string(&d2.transact()), "abc".to_string());
2055 assert_eq!(delta2.swap(None), expected);
2056 }
2057
2058 {
2060 let mut txn = d1.transact_mut();
2061 txt1.remove_range(&mut txn, 0, 1);
2062 let update = txn.encode_update_v1();
2063 drop(txn);
2064
2065 let expected = Some(Arc::new(vec![Delta::Deleted(1)]));
2066
2067 assert_eq!(txt1.get_string(&d1.transact()), "bc".to_string());
2068 assert_eq!(
2069 txt1.diff(&d1.transact(), YChange::identity),
2070 vec![Diff::new("bc".into(), Some(Box::new(a.clone())))]
2071 );
2072 assert_eq!(delta1.swap(None), expected);
2073
2074 let mut txn = d2.transact_mut();
2075 txn.apply_update(Update::decode_v1(update.as_slice()).unwrap())
2076 .unwrap();
2077 drop(txn);
2078
2079 assert_eq!(txt2.get_string(&d2.transact()), "bc".to_string());
2080 assert_eq!(delta2.swap(None), expected);
2081 }
2082
2083 {
2085 let mut txn = d1.transact_mut();
2086 txt1.remove_range(&mut txn, 1, 1);
2087 let update = txn.encode_update_v1();
2088 drop(txn);
2089
2090 let expected = Some(Arc::new(vec![Delta::Retain(1, None), Delta::Deleted(1)]));
2091
2092 assert_eq!(txt1.get_string(&d1.transact()), "b".to_string());
2093 assert_eq!(
2094 txt1.diff(&d1.transact(), YChange::identity),
2095 vec![Diff::new("b".into(), Some(Box::new(a.clone())))]
2096 );
2097 assert_eq!(delta1.swap(None), expected);
2098
2099 let mut txn = d2.transact_mut();
2100 txn.apply_update(Update::decode_v1(update.as_slice()).unwrap())
2101 .unwrap();
2102 drop(txn);
2103
2104 assert_eq!(txt2.get_string(&d2.transact()), "b".to_string());
2105 assert_eq!(delta2.swap(None), expected);
2106 }
2107
2108 {
2110 let mut txn = d1.transact_mut();
2111 txt1.insert_with_attributes(&mut txn, 0, "z", a.clone());
2112 let update = txn.encode_update_v1();
2113 drop(txn);
2114
2115 let expected = Some(Arc::new(vec![Delta::Inserted(
2116 "z".into(),
2117 Some(Box::new(a.clone())),
2118 )]));
2119
2120 assert_eq!(txt1.get_string(&d1.transact()), "zb".to_string());
2121 assert_eq!(
2122 txt1.diff(&mut d1.transact_mut(), YChange::identity),
2123 vec![Diff::new("zb".into(), Some(Box::new(a.clone())))]
2124 );
2125 assert_eq!(delta1.swap(None), expected);
2126
2127 let mut txn = d2.transact_mut();
2128 txn.apply_update(Update::decode_v1(update.as_slice()).unwrap())
2129 .unwrap();
2130 drop(txn);
2131
2132 assert_eq!(txt2.get_string(&d2.transact()), "zb".to_string());
2133 assert_eq!(delta2.swap(None), expected);
2134 }
2135
2136 {
2138 let mut txn = d1.transact_mut();
2139 txt1.insert(&mut txn, 0, "y");
2140 let update = txn.encode_update_v1();
2141 drop(txn);
2142
2143 let expected = Some(Arc::new(vec![Delta::Inserted("y".into(), None)]));
2144
2145 assert_eq!(txt1.get_string(&d1.transact()), "yzb".to_string());
2146 assert_eq!(
2147 txt1.diff(&mut d1.transact_mut(), YChange::identity),
2148 vec![
2149 Diff::new("y".into(), None),
2150 Diff::new("zb".into(), Some(Box::new(a.clone())))
2151 ]
2152 );
2153 assert_eq!(delta1.swap(None), expected);
2154
2155 let mut txn = d2.transact_mut();
2156 txn.apply_update(Update::decode_v1(update.as_slice()).unwrap())
2157 .unwrap();
2158 drop(txn);
2159
2160 assert_eq!(txt2.get_string(&d2.transact()), "yzb".to_string());
2161 assert_eq!(delta2.swap(None), expected);
2162 }
2163
2164 {
2166 let mut txn = d1.transact_mut();
2167 let b: Attrs = HashMap::from([("bold".into(), Any::Null)]);
2168 txt1.format(&mut txn, 0, 2, b.clone());
2169 let update = txn.encode_update_v1();
2170 drop(txn);
2171
2172 let expected = Some(Arc::new(vec![
2173 Delta::Retain(1, None),
2174 Delta::Retain(1, Some(Box::new(b))),
2175 ]));
2176
2177 assert_eq!(txt1.get_string(&d1.transact()), "yzb".to_string());
2178 assert_eq!(
2179 txt1.diff(&mut d1.transact_mut(), YChange::identity),
2180 vec![
2181 Diff::new("yz".into(), None),
2182 Diff::new("b".into(), Some(Box::new(a.clone())))
2183 ]
2184 );
2185 assert_eq!(delta1.swap(None), expected);
2186
2187 let mut txn = d2.transact_mut();
2188 txn.apply_update(Update::decode_v1(update.as_slice()).unwrap())
2189 .unwrap();
2190 drop(txn);
2191
2192 assert_eq!(txt2.get_string(&d2.transact()), "yzb".to_string());
2193 assert_eq!(delta2.swap(None), expected);
2194 }
2195 }
2196
2197 #[test]
2198 fn embed_with_attributes() {
2199 let d1 = Doc::with_client_id(1);
2200 let txt1 = d1.get_or_insert_text("text");
2201
2202 let delta1 = Arc::new(ArcSwapOption::default());
2203 let delta_clone = delta1.clone();
2204 let _sub1 = txt1.observe(move |txn, e| {
2205 let delta = e.delta(txn).to_vec();
2206 delta_clone.store(Some(Arc::new(delta)));
2207 });
2208
2209 let a1: Attrs = HashMap::from([("bold".into(), true.into())]);
2210 let embed = any!({
2211 "image": "imageSrc.png"
2212 });
2213
2214 let (update_v1, update_v2) = {
2215 let mut txn = d1.transact_mut();
2216 txt1.insert_with_attributes(&mut txn, 0, "ab", a1.clone());
2217
2218 let a2: Attrs = HashMap::from([("width".into(), Any::Number(100.0))]);
2219
2220 txt1.insert_embed_with_attributes(&mut txn, 1, embed.clone(), a2.clone());
2221 drop(txn);
2222
2223 let a1 = Some(Box::new(a1.clone()));
2224 let a2 = Some(Box::new(a2.clone()));
2225
2226 let expected = Some(Arc::new(vec![
2227 Delta::Inserted("a".into(), a1.clone()),
2228 Delta::Inserted(embed.clone().into(), a2.clone()),
2229 Delta::Inserted("b".into(), a1.clone()),
2230 ]));
2231 assert_eq!(delta1.swap(None), expected);
2232
2233 let expected = vec![
2234 Diff::new("a".into(), a1.clone()),
2235 Diff::new(embed.clone().into(), a2),
2236 Diff::new("b".into(), a1.clone()),
2237 ];
2238 let mut txn = d1.transact_mut();
2239 assert_eq!(txt1.diff(&mut txn, YChange::identity), expected);
2240
2241 let update_v1 = txn.encode_state_as_update_v1(&StateVector::default());
2242 let update_v2 = txn.encode_state_as_update_v2(&StateVector::default());
2243 (update_v1, update_v2)
2244 };
2245
2246 let a1 = Some(Box::new(a1));
2247 let a2 = Some(Box::new(HashMap::from([(
2248 "width".into(),
2249 Any::Number(100.0),
2250 )])));
2251
2252 let expected = vec![
2253 Diff::new("a".into(), a1.clone()),
2254 Diff::new(embed.into(), a2),
2255 Diff::new("b".into(), a1.clone()),
2256 ];
2257
2258 let d2 = Doc::new();
2259 let txt2 = d2.get_or_insert_text("text");
2260 {
2261 let txn = &mut d2.transact_mut();
2262 let update = Update::decode_v1(&update_v1).unwrap();
2263 txn.apply_update(update).unwrap();
2264 assert_eq!(txt2.diff(txn, YChange::identity), expected);
2265 }
2266
2267 let d3 = Doc::new();
2268 let txt3 = d3.get_or_insert_text("text");
2269 {
2270 let txn = &mut d3.transact_mut();
2271 let update = Update::decode_v2(&update_v2).unwrap();
2272 txn.apply_update(update).unwrap();
2273 let actual = txt3.diff(txn, YChange::identity);
2274 assert_eq!(actual, expected);
2275 }
2276 }
2277
2278 #[test]
2279 fn issue_101() {
2280 let d1 = Doc::with_client_id(1);
2281 let txt1 = d1.get_or_insert_text("text");
2282 let delta = Arc::new(ArcSwapOption::default());
2283 let delta_copy = delta.clone();
2284
2285 let attrs: Attrs = HashMap::from([("bold".into(), true.into())]);
2286
2287 txt1.insert(&mut d1.transact_mut(), 0, "abcd");
2288
2289 let _sub = txt1.observe(move |txn, e| {
2290 delta_copy.store(Some(e.delta(txn).to_vec().into()));
2291 });
2292 txt1.format(&mut d1.transact_mut(), 1, 2, attrs.clone());
2293
2294 let expected = Arc::new(vec![
2295 Delta::Retain(1, None),
2296 Delta::Retain(2, Some(Box::new(attrs))),
2297 ]);
2298 let actual = delta.load_full();
2299 assert_eq!(actual, Some(expected));
2300 }
2301
2302 #[test]
2303 fn yrs_delete() {
2304 let doc = Doc::with_options(Options {
2305 offset_kind: OffsetKind::Utf16,
2306 ..Default::default()
2307 });
2308
2309 let text1 = r#"
2310 Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Eleifend mi in nulla posuere sollicitudin. Lorem mollis aliquam ut porttitor. Enim ut sem viverra aliquet eget sit amet. Sed turpis tincidunt id aliquet risus feugiat in ante metus. Accumsan lacus vel facilisis volutpat. Non consectetur a erat nam at lectus urna. Enim diam vulputate ut pharetra sit amet. In dictum non consectetur a erat. Bibendum at varius vel pharetra vel turpis nunc eget lorem. Blandit cursus risus at ultrices. Sed lectus vestibulum mattis ullamcorper velit sed ullamcorper. Sagittis nisl rhoncus mattis rhoncus.
2311
2312 Sed vulputate odio ut enim. Erat pellentesque adipiscing commodo elit at imperdiet dui. Ultricies tristique nulla aliquet enim tortor at auctor urna nunc. Tincidunt eget nullam non nisi est sit amet. Sed adipiscing diam donec adipiscing tristique risus nec. Risus commodo viverra maecenas accumsan lacus vel facilisis volutpat est. Donec enim diam vulputate ut pharetra sit amet aliquam id. Netus et malesuada fames ac turpis egestas sed tempus urna. Augue mauris augue neque gravida. Tellus orci ac auctor augue mauris augue. Ante metus dictum at tempor. Feugiat in ante metus dictum at. Vitae elementum curabitur vitae nunc sed velit dignissim. Non arcu risus quis varius quam quisque id diam vel. Fermentum leo vel orci porta non. Donec adipiscing tristique risus nec feugiat in fermentum posuere. Duis convallis convallis tellus id interdum velit laoreet id. Vel eros donec ac odio tempor orci dapibus ultrices in. At varius vel pharetra vel turpis nunc eget lorem. Blandit aliquam etiam erat velit scelerisque in.
2313 "#;
2314
2315 let text2 = r#"test"#;
2316
2317 {
2318 let text = doc.get_or_insert_text("content");
2319 let mut txn = doc.transact_mut();
2320 text.insert(&mut txn, 0, text1);
2321 txn.commit();
2322 }
2323
2324 {
2325 let text = doc.get_or_insert_text("content");
2326 let mut txn = doc.transact_mut();
2327 text.insert(&mut txn, 100, text2);
2328 txn.commit();
2329 }
2330
2331 {
2332 let text = doc.get_or_insert_text("content");
2333 let mut txn = doc.transact_mut();
2334
2335 let c1 = text1.chars().count();
2336 let c2 = text2.chars().count();
2337 let count = c1 as u32 + c2 as u32;
2338
2339 let _observer = text
2340 .observe(move |txn, edit| assert_eq!(edit.delta(txn)[0], Delta::Deleted(count)));
2341
2342 text.remove_range(&mut txn, 0, count);
2343 txn.commit();
2344 }
2345
2346 {
2347 let text = doc.get_or_insert_text("content");
2348 assert_eq!(text.get_string(&doc.transact()), "");
2349 }
2350 }
2351
2352 #[test]
2353 fn text_diff_adjacent() {
2354 let doc = Doc::with_client_id(1);
2355 let txt = doc.get_or_insert_text("text");
2356 let mut txn = doc.transact_mut();
2357 let attrs1 = Attrs::from([("a".into(), "a".into())]);
2358 txt.insert_with_attributes(&mut txn, 0, "abc", attrs1.clone());
2359 let attrs2 = Attrs::from([("a".into(), "a".into()), ("b".into(), "b".into())]);
2360 txt.insert_with_attributes(&mut txn, 3, "def", attrs2.clone());
2361
2362 let diff = txt.diff(&mut txn, YChange::identity);
2363 let expected = vec![
2364 Diff::new("abc".into(), Some(Box::new(attrs1))),
2365 Diff::new("def".into(), Some(Box::new(attrs2))),
2366 ];
2367 assert_eq!(diff, expected);
2368 }
2369
2370 #[test]
2371 fn text_remove_4_byte_range() {
2372 let d1 = Doc::new();
2373 let txt = d1.get_or_insert_text("test");
2374
2375 txt.insert(&mut d1.transact_mut(), 0, "😭😊");
2376
2377 let d2 = Doc::new();
2378 exchange_updates(&[&d1, &d2]);
2379
2380 txt.remove_range(&mut d1.transact_mut(), 0, "😭".len() as u32);
2381 assert_eq!(txt.get_string(&d1.transact()).as_str(), "😊");
2382
2383 exchange_updates(&[&d1, &d2]);
2384 let txt = d2.get_or_insert_text("test");
2385 assert_eq!(txt.get_string(&d2.transact()).as_str(), "😊");
2386 }
2387
2388 #[test]
2389 fn text_remove_3_byte_range() {
2390 let d1 = Doc::new();
2391 let txt = d1.get_or_insert_text("test");
2392
2393 txt.insert(&mut d1.transact_mut(), 0, "⏰⏳");
2394
2395 let d2 = Doc::new();
2396 exchange_updates(&[&d1, &d2]);
2397
2398 txt.remove_range(&mut d1.transact_mut(), 0, "⏰".len() as u32);
2399 assert_eq!(txt.get_string(&d1.transact()).as_str(), "⏳");
2400
2401 exchange_updates(&[&d1, &d2]);
2402 let txt = d2.get_or_insert_text("test");
2403 assert_eq!(txt.get_string(&d2.transact()).as_str(), "⏳");
2404 }
2405 #[test]
2406 fn delete_4_byte_character_from_middle() {
2407 let doc = Doc::new();
2408 let txt = doc.get_or_insert_text("test");
2409 let mut txn = doc.transact_mut();
2410
2411 txt.insert(&mut txn, 0, "😊😭");
2412 txt.remove_range(&mut txn, "😊".len() as u32, "😭".len() as u32);
2415
2416 assert_eq!(txt.get_string(&txn).as_str(), "😊");
2417 }
2418
2419 #[test]
2420 fn delete_3_byte_character_from_middle_1() {
2421 let doc = Doc::new();
2422 let txt = doc.get_or_insert_text("test");
2423 let mut txn = doc.transact_mut();
2424
2425 txt.insert(&mut txn, 0, "⏰⏳");
2426 txt.remove_range(&mut txn, "⏰".len() as u32, "⏳".len() as u32);
2429
2430 assert_eq!(txt.get_string(&txn).as_str(), "⏰");
2431 }
2432
2433 #[test]
2434 fn delete_3_byte_character_from_middle_2() {
2435 let doc = Doc::new();
2436 let txt = doc.get_or_insert_text("test");
2437 let mut txn = doc.transact_mut();
2438
2439 txt.insert(&mut txn, 0, "👯🙇♀️🙇♀️⏰👩❤️💋👨");
2440
2441 txt.format(
2442 &mut txn,
2443 "👯".len() as u32,
2444 "🙇♀️🙇♀️".len() as u32,
2445 HashMap::new(),
2446 );
2447 txt.remove_range(&mut txn, "👯🙇♀️🙇♀️".len() as u32, "⏰".len() as u32); assert_eq!(txt.get_string(&txn).as_str(), "👯🙇♀️🙇♀️👩❤️💋👨");
2450 }
2451
2452 #[test]
2453 fn delete_3_byte_character_from_middle_after_insert_and_format() {
2454 let doc = Doc::new();
2455 let txt = doc.get_or_insert_text("test");
2456 let mut txn = doc.transact_mut();
2457
2458 txt.insert(&mut txn, 0, "🙇♀️🙇♀️⏰👩❤️💋👨");
2459 txt.insert(&mut txn, 0, "👯");
2460 txt.format(
2461 &mut txn,
2462 "👯".len() as u32,
2463 "🙇♀️🙇♀️".len() as u32,
2464 HashMap::new(),
2465 );
2466
2467 txt.remove_range(&mut txn, "👯🙇♀️🙇♀️".len() as u32, "⏰".len() as u32); assert_eq!(&txt.get_string(&txn), "👯🙇♀️🙇♀️👩❤️💋👨");
2471 }
2472
2473 #[test]
2474 fn delete_multi_byte_character_from_middle_after_insert_and_format() {
2475 let doc = Doc::with_client_id(1);
2476 let txt = doc.get_or_insert_text("test");
2477 let mut txn = doc.transact_mut();
2478
2479 txt.insert(&mut txn, 0, "❤️❤️🙇♀️🙇♀️⏰👩❤️💋👨👩❤️💋👨");
2480 txt.insert(&mut txn, 0, "👯");
2481 txt.format(
2482 &mut txn,
2483 "👯".len() as u32,
2484 "❤️❤️🙇♀️🙇♀️⏰".len() as u32,
2485 HashMap::new(),
2486 );
2487 txt.insert(&mut txn, "👯❤️❤️🙇♀️🙇♀️⏰".len() as u32, "⏰");
2488 txt.format(
2489 &mut txn,
2490 "👯❤️❤️🙇♀️🙇♀️⏰⏰".len() as u32,
2491 "👩❤️💋👨".len() as u32,
2492 HashMap::new(),
2493 );
2494 txt.remove_range(&mut txn, "👯❤️❤️🙇♀️🙇♀️⏰⏰👩❤️💋👩".len() as u32, "👩❤️💋👨".len() as u32);
2495 assert_eq!(txt.get_string(&txn).as_str(), "👯❤️❤️🙇♀️🙇♀️⏰⏰👩❤️💋👨");
2496 }
2497
2498 #[test]
2499 fn insert_string_with_no_attribute() {
2500 let doc = Doc::new();
2501 let txt = doc.get_or_insert_text("test");
2502 let mut txn = doc.transact_mut();
2503
2504 let attrs = Attrs::from([("a".into(), "a".into())]);
2505 txt.insert_with_attributes(&mut txn, 0, "ac", attrs.clone());
2506 txt.insert_with_attributes(&mut txn, 1, "b", Attrs::new());
2507
2508 let expect = vec![
2509 Diff::new("a".into(), Some(Box::new(attrs.clone()))),
2510 Diff::new("b".into(), None),
2511 Diff::new("c".into(), Some(Box::new(attrs.clone()))),
2512 ];
2513
2514 assert!(txt.diff(&mut txn, YChange::identity).eq(&expect))
2515 }
2516
2517 #[test]
2518 fn insert_empty_string_with_attributes() {
2519 let doc = Doc::new();
2520 let txt = doc.get_or_insert_text("test");
2521 let mut txn = doc.transact_mut();
2522
2523 let attrs = Attrs::from([("a".into(), "a".into())]);
2524 txt.insert(&mut txn, 0, "abc");
2525 txt.insert(&mut txn, 1, ""); txt.insert_with_attributes(&mut txn, 1, "", attrs); assert_eq!(txt.get_string(&txn).as_str(), "abc");
2529
2530 let bin = txn.encode_state_as_update_v1(&StateVector::default());
2531
2532 let doc = Doc::new();
2533 let txt = doc.get_or_insert_text("test");
2534 let mut txn = doc.transact_mut();
2535 let update = Update::decode_v1(bin.as_slice()).unwrap();
2536 txn.apply_update(update).unwrap();
2537
2538 assert_eq!(txt.get_string(&txn).as_str(), "abc");
2539 }
2540
2541 #[test]
2542 fn snapshots() {
2543 let doc = Doc::with_client_id(1);
2544 let text = doc.get_or_insert_text("text");
2545 text.insert(&mut doc.transact_mut(), 0, "hello");
2546 let prev = doc.transact_mut().snapshot();
2547 text.insert(&mut doc.transact_mut(), 5, " world");
2548 let next = doc.transact_mut().snapshot();
2549 let diff = text.diff_range(
2550 &mut doc.transact_mut(),
2551 Some(&next),
2552 Some(&prev),
2553 YChange::identity,
2554 );
2555
2556 assert_eq!(
2557 diff,
2558 vec![
2559 Diff::new("hello".into(), None),
2560 Diff::with_change(
2561 " world".into(),
2562 None,
2563 Some(YChange::new(
2564 ChangeKind::Added,
2565 ID::new(ClientID::new(1), 5)
2566 ))
2567 )
2568 ]
2569 )
2570 }
2571
2572 #[test]
2573 fn diff_with_embedded_items() {
2574 let doc = Doc::new();
2575 let text = doc.get_or_insert_text("article");
2576 let mut txn = doc.transact_mut();
2577
2578 let bold = Attrs::from([("b".into(), true.into())]);
2579 let italic = Attrs::from([("i".into(), true.into())]);
2580
2581 text.insert_with_attributes(&mut txn, 0, "hello world", italic.clone()); text.format(&mut txn, 6, 5, bold.clone()); let image = vec![0, 0, 0, 0];
2584 text.insert_embed(&mut txn, 5, image.clone()); let array = text.insert_embed(&mut txn, 5, ArrayPrelim::default()); let italic_and_bold = Attrs::from([("b".into(), true.into()), ("i".into(), true.into())]);
2588 let chunks = text.diff(&txn, YChange::identity);
2589 assert_eq!(
2590 chunks,
2591 vec![
2592 Diff::new("hello".into(), Some(Box::new(italic.clone()))),
2593 Diff::new(Out::YArray(array), Some(Box::new(italic.clone()))),
2594 Diff::new(image.into(), Some(Box::new(italic.clone()))),
2595 Diff::new(" ".into(), Some(Box::new(italic))),
2596 Diff::new("world".into(), Some(Box::new(italic_and_bold))),
2597 ]
2598 );
2599 }
2600
2601 #[test]
2602 fn multi_threading() {
2603 use std::sync::{Arc, RwLock};
2604 use std::thread::{sleep, spawn};
2605
2606 let doc = Arc::new(RwLock::new(Doc::with_client_id(1)));
2607
2608 let d2 = doc.clone();
2609 let h2 = spawn(move || {
2610 for _ in 0..10 {
2611 let millis = fastrand::u64(1..20);
2612 sleep(Duration::from_millis(millis));
2613
2614 let doc = d2.write().unwrap();
2615 let txt = doc.get_or_insert_text("test");
2616 let mut txn = doc.transact_mut();
2617 txt.push(&mut txn, "a");
2618 }
2619 });
2620
2621 let d3 = doc.clone();
2622 let h3 = spawn(move || {
2623 for _ in 0..10 {
2624 let millis = fastrand::u64(1..20);
2625 sleep(Duration::from_millis(millis));
2626
2627 let doc = d3.write().unwrap();
2628 let txt = doc.get_or_insert_text("test");
2629 let mut txn = doc.transact_mut();
2630 txt.push(&mut txn, "b");
2631 }
2632 });
2633
2634 h3.join().unwrap();
2635 h2.join().unwrap();
2636
2637 let doc = doc.read().unwrap();
2638 let txt = doc.get_or_insert_text("test");
2639 let len = txt.len(&doc.transact());
2640 assert_eq!(len, 20);
2641 }
2642
2643 #[test]
2644 fn multiline_format() {
2645 let doc = Doc::with_client_id(1);
2646 let mut txn = doc.transact_mut();
2647 let txt = txn.get_or_insert_text("text");
2648 let bold: Option<Box<Attrs>> = Some(Box::new(Attrs::from([("bold".into(), true.into())])));
2649 txt.insert(&mut txn, 0, "Test\nMulti-line\nFormatting");
2650 txt.apply_delta(
2651 &mut txn,
2652 [
2653 Delta::Retain(4, bold.clone()),
2654 Delta::retain(1), Delta::Retain(10, bold.clone()),
2656 Delta::retain(1), Delta::Retain(10, bold.clone()),
2658 ],
2659 );
2660 let delta = txt.diff(&txn, YChange::identity);
2661 assert_eq!(
2662 delta,
2663 vec![
2664 Diff::new("Test".into(), bold.clone()),
2665 Diff::new("\n".into(), None),
2666 Diff::new("Multi-line".into(), bold.clone()),
2667 Diff::new("\n".into(), None),
2668 Diff::new("Formatting".into(), bold),
2669 ]
2670 );
2671 }
2672
2673 #[test]
2674 fn delta_with_embeds() {
2675 let doc = Doc::with_client_id(1);
2676 let mut txn = doc.transact_mut();
2677 let txt = txn.get_or_insert_text("text");
2678 let linebreak = any!({
2679 "linebreak": "s"
2680 });
2681 txt.apply_delta(&mut txn, [Delta::insert(linebreak.clone())]);
2682 let delta = txt.diff(&txn, YChange::identity);
2683 assert_eq!(delta, vec![Diff::new(linebreak.into(), None)]);
2684 }
2685
2686 #[test]
2687 fn delta_with_shared_ref() {
2688 let d1 = Doc::with_client_id(1);
2689 let mut txn1 = d1.transact_mut();
2690 let txt1 = txn1.get_or_insert_text("text");
2691 txt1.apply_delta(
2692 &mut txn1,
2693 [Delta::insert(MapPrelim::from([("key", "val")]))],
2694 );
2695 let delta = txt1.diff(&txn1, YChange::identity);
2696 let d: MapRef = delta[0].insert.clone().cast().unwrap();
2697 assert_eq!(d.get(&txn1, "key").unwrap(), Out::Any("val".into()));
2698
2699 let triggered = Arc::new(AtomicBool::new(false));
2700 let _sub = {
2701 let triggered = triggered.clone();
2702 txt1.observe(move |txn, e| {
2703 let delta = e.delta(txn).to_vec();
2704 let d: MapRef = match &delta[0] {
2705 Delta::Inserted(insert, _) => insert.clone().cast().unwrap(),
2706 _ => unreachable!("unexpected delta"),
2707 };
2708 assert_eq!(d.get(txn, "key").unwrap(), Out::Any("val".into()));
2709 triggered.store(true, Ordering::Relaxed);
2710 })
2711 };
2712
2713 let d2 = Doc::with_client_id(2);
2714 let mut txn2 = d2.transact_mut();
2715 let txt2 = txn2.get_or_insert_text("text");
2716 let update = Update::decode_v1(&txn1.encode_update_v1()).unwrap();
2717 txn2.apply_update(update).unwrap();
2718 drop(txn1);
2719 drop(txn2);
2720
2721 assert!(triggered.load(Ordering::Relaxed), "fired event");
2722
2723 let delta = txt2.diff(&d2.transact(), YChange::identity);
2724 assert_eq!(delta.len(), 1);
2725 let d: MapRef = delta[0].insert.clone().cast().unwrap();
2726 assert_eq!(
2727 d.get(&d2.transact(), "key").unwrap(),
2728 Out::Any("val".into())
2729 );
2730 }
2731
2732 #[test]
2733 fn delta_snapshots() {
2734 let doc = Doc::with_options(Options {
2735 client_id: ClientID::new(1),
2736 skip_gc: true,
2737 ..Default::default()
2738 });
2739 let mut txn = doc.transact_mut();
2740 let txt = txn.get_or_insert_text("text");
2741 txt.apply_delta(&mut txn, [Delta::insert("abcd")]);
2742 let snapshot1 = txn.snapshot(); txt.apply_delta(
2744 &mut txn,
2745 [Delta::retain(1), Delta::insert("x"), Delta::delete(1)],
2746 );
2747 let snapshot2 = txn.snapshot(); txt.apply_delta(
2749 &mut txn,
2750 [
2751 Delta::retain(2), Delta::delete(1), Delta::insert("x"), Delta::delete(1), ],
2756 );
2757 let state1 = txt.diff_range(&mut txn, Some(&snapshot1), None, YChange::identity);
2758 assert_eq!(state1, vec![Diff::new("abcd".into(), None)]);
2759 let state2 = txt.diff_range(&mut txn, Some(&snapshot2), None, YChange::identity);
2760 assert_eq!(state2, vec![Diff::new("axcd".into(), None)]);
2761 let state2_diff = txt.diff_range(
2762 &mut txn,
2763 Some(&snapshot2),
2764 Some(&snapshot1),
2765 YChange::identity,
2766 );
2767 assert_eq!(
2768 state2_diff,
2769 vec![
2770 Diff {
2771 insert: "a".into(),
2772 attributes: None,
2773 ychange: None
2774 },
2775 Diff {
2776 insert: "x".into(),
2777 attributes: None,
2778 ychange: Some(YChange {
2779 kind: ChangeKind::Added,
2780 id: ID::new(ClientID::new(1), 4)
2781 })
2782 },
2783 Diff {
2784 insert: "b".into(),
2785 attributes: None,
2786 ychange: Some(YChange {
2787 kind: ChangeKind::Removed,
2788 id: ID::new(ClientID::new(1), 1)
2789 })
2790 },
2791 Diff {
2792 insert: "cd".into(),
2793 attributes: None,
2794 ychange: None
2795 }
2796 ]
2797 );
2798 }
2799
2800 #[test]
2801 fn snapshot_delete_after() {
2802 let doc = Doc::with_options(Options {
2803 client_id: ClientID::new(1),
2804 skip_gc: true,
2805 ..Default::default()
2806 });
2807 let mut txn = doc.transact_mut();
2808 let txt = txn.get_or_insert_text("text");
2809 txt.apply_delta(&mut txn, [Delta::insert("abcd")]);
2810 let snapshot1 = txn.snapshot();
2811 txt.apply_delta(&mut txn, [Delta::retain(4), Delta::insert("e")]);
2812 let state1 = txt.diff_range(&mut txn, Some(&snapshot1), None, YChange::identity);
2813 assert_eq!(state1, vec![Diff::new("abcd".into(), None)]);
2814 }
2815
2816 #[test]
2817 fn empty_delta_chunks() {
2818 let doc = Doc::with_client_id(1);
2819 let mut txn = doc.transact_mut();
2820 let txt = txn.get_or_insert_text("text");
2821
2822 let delta = vec![
2823 Delta::insert("a"),
2824 Delta::Inserted(
2825 "".into(),
2826 Some(Box::new(Attrs::from([(
2827 Arc::from("bold"),
2828 Any::from(true),
2829 )]))),
2830 ),
2831 Delta::insert("b"),
2832 ];
2833
2834 txt.apply_delta(&mut txn, delta);
2835 assert_eq!(txt.get_string(&txn), "ab");
2836
2837 let bin = txn.encode_state_as_update_v1(&StateVector::default());
2838
2839 let doc2 = Doc::with_client_id(2);
2840 let mut txn = doc2.transact_mut();
2841 let txt = txn.get_or_insert_text("text");
2842
2843 let update = Update::decode_v1(bin.as_slice()).unwrap();
2844 txn.apply_update(update).unwrap();
2845 assert_eq!(txt.get_string(&txn), "ab");
2846 }
2847}