1use std::borrow::Borrow;
2use std::cell::UnsafeCell;
3use std::collections::{HashMap, HashSet};
4use std::convert::{TryFrom, TryInto};
5use std::fmt::Write;
6use std::marker::PhantomData;
7use std::ops::{Deref, DerefMut};
8use std::sync::Arc;
9
10use crate::block::{EmbedPrelim, Item, ItemContent, ItemPosition, ItemPtr, Prelim};
11use crate::block_iter::BlockIter;
12use crate::transaction::TransactionMut;
13use crate::types::text::{diff_between, TextEvent, YChange};
14use crate::types::{
15 event_change_set, event_keys, AsPrelim, Branch, BranchPtr, Change, ChangeSet, DefaultPrelim,
16 Delta, Entries, EntryChange, MapRef, Out, Path, RootRef, SharedRef, ToJson, TypePtr, TypeRef,
17};
18use crate::{
19 Any, ArrayRef, BranchID, DeepObservable, GetString, In, IndexedSequence, Map, Observable,
20 ReadTxn, StickyIndex, Text, TextRef, ID,
21};
22
23pub trait XmlPrelim: Prelim {}
24
25#[derive(Debug, Clone, PartialEq)]
28pub enum XmlIn {
29 Text(XmlDeltaPrelim),
30 Element(XmlElementPrelim),
31 Fragment(XmlFragmentPrelim),
32}
33
34impl From<XmlDeltaPrelim> for XmlIn {
35 #[inline]
36 fn from(value: XmlDeltaPrelim) -> Self {
37 Self::Text(value)
38 }
39}
40
41impl From<XmlTextPrelim> for XmlIn {
42 #[inline]
43 fn from(value: XmlTextPrelim) -> Self {
44 Self::Text(value.into())
45 }
46}
47
48impl From<XmlElementPrelim> for XmlIn {
49 #[inline]
50 fn from(value: XmlElementPrelim) -> Self {
51 Self::Element(value)
52 }
53}
54
55impl From<XmlFragmentPrelim> for XmlIn {
56 #[inline]
57 fn from(value: XmlFragmentPrelim) -> Self {
58 Self::Fragment(value)
59 }
60}
61
62impl XmlPrelim for XmlIn {}
63
64impl Prelim for XmlIn {
65 type Return = XmlOut;
66
67 fn into_content(self, _txn: &mut TransactionMut) -> (ItemContent, Option<Self>) {
68 let type_ref = match &self {
69 XmlIn::Text(_) => TypeRef::XmlText,
70 XmlIn::Element(prelim) => TypeRef::XmlElement(prelim.tag.clone()),
71 XmlIn::Fragment(_) => TypeRef::XmlFragment,
72 };
73 (ItemContent::Type(Branch::new(type_ref)), Some(self))
74 }
75
76 fn integrate(self, txn: &mut TransactionMut, inner_ref: BranchPtr) {
77 match self {
78 XmlIn::Text(prelim) => prelim.integrate(txn, inner_ref),
79 XmlIn::Element(prelim) => prelim.integrate(txn, inner_ref),
80 XmlIn::Fragment(prelim) => prelim.integrate(txn, inner_ref),
81 }
82 }
83}
84
85#[derive(Debug, Clone)]
89pub enum XmlOut {
90 Element(XmlElementRef),
91 Fragment(XmlFragmentRef),
92 Text(XmlTextRef),
93}
94
95impl XmlOut {
96 pub fn as_ptr(&self) -> BranchPtr {
97 match self {
98 XmlOut::Element(n) => n.0,
99 XmlOut::Fragment(n) => n.0,
100 XmlOut::Text(n) => n.0,
101 }
102 }
103
104 pub fn id(&self) -> BranchID {
105 self.as_ptr().id()
106 }
107
108 pub fn into_xml_element(self) -> Option<XmlElementRef> {
111 match self {
112 XmlOut::Element(n) => Some(n),
113 _ => None,
114 }
115 }
116
117 pub fn into_xml_fragment(self) -> Option<XmlFragmentRef> {
120 match self {
121 XmlOut::Fragment(n) => Some(n),
122 _ => None,
123 }
124 }
125
126 pub fn into_xml_text(self) -> Option<XmlTextRef> {
129 match self {
130 XmlOut::Text(n) => Some(n),
131 _ => None,
132 }
133 }
134}
135
136impl AsRef<Branch> for XmlOut {
137 fn as_ref(&self) -> &Branch {
138 match self {
139 XmlOut::Element(n) => n.as_ref(),
140 XmlOut::Fragment(n) => n.as_ref(),
141 XmlOut::Text(n) => n.as_ref(),
142 }
143 }
144}
145
146impl TryInto<XmlElementRef> for XmlOut {
147 type Error = XmlOut;
148
149 fn try_into(self) -> Result<XmlElementRef, Self::Error> {
150 match self {
151 XmlOut::Element(xml) => Ok(xml),
152 other => Err(other),
153 }
154 }
155}
156
157impl TryInto<XmlTextRef> for XmlOut {
158 type Error = XmlOut;
159
160 fn try_into(self) -> Result<XmlTextRef, Self::Error> {
161 match self {
162 XmlOut::Text(xml) => Ok(xml),
163 other => Err(other),
164 }
165 }
166}
167
168impl TryInto<XmlFragmentRef> for XmlOut {
169 type Error = XmlOut;
170
171 fn try_into(self) -> Result<XmlFragmentRef, Self::Error> {
172 match self {
173 XmlOut::Fragment(xml) => Ok(xml),
174 other => Err(other),
175 }
176 }
177}
178
179impl TryFrom<BranchPtr> for XmlOut {
180 type Error = BranchPtr;
181
182 fn try_from(value: BranchPtr) -> Result<Self, Self::Error> {
183 match value.type_ref {
184 TypeRef::XmlElement(_) => Ok(XmlOut::Element(XmlElementRef::from(value))),
185 TypeRef::XmlFragment => Ok(XmlOut::Fragment(XmlFragmentRef::from(value))),
186 TypeRef::XmlText => Ok(XmlOut::Text(XmlTextRef::from(value))),
187 _ => Err(value),
188 }
189 }
190}
191
192impl TryFrom<Out> for XmlOut {
193 type Error = Out;
194
195 fn try_from(value: Out) -> Result<Self, Self::Error> {
196 match value {
197 Out::YXmlElement(n) => Ok(XmlOut::Element(n)),
198 Out::YXmlFragment(n) => Ok(XmlOut::Fragment(n)),
199 Out::YXmlText(n) => Ok(XmlOut::Text(n)),
200 other => Err(other),
201 }
202 }
203}
204
205impl From<XmlOut> for Out {
206 fn from(value: XmlOut) -> Self {
207 match value {
208 XmlOut::Element(xml) => Out::YXmlElement(xml),
209 XmlOut::Fragment(xml) => Out::YXmlFragment(xml),
210 XmlOut::Text(xml) => Out::YXmlText(xml),
211 }
212 }
213}
214
215impl TryFrom<ItemPtr> for XmlOut {
216 type Error = ItemPtr;
217
218 fn try_from(value: ItemPtr) -> Result<Self, Self::Error> {
219 if let Some(branch) = value.clone().as_branch() {
220 match branch.type_ref {
221 TypeRef::XmlElement(_) => Ok(XmlOut::Element(XmlElementRef::from(branch))),
222 TypeRef::XmlFragment => Ok(XmlOut::Fragment(XmlFragmentRef::from(branch))),
223 TypeRef::XmlText => Ok(XmlOut::Text(XmlTextRef::from(branch))),
224 _ => return Err(value),
225 }
226 } else {
227 Err(value)
228 }
229 }
230}
231
232#[repr(transparent)]
246#[derive(Debug, Clone)]
247pub struct XmlElementRef(BranchPtr);
248
249impl SharedRef for XmlElementRef {}
250impl Xml for XmlElementRef {}
251impl XmlFragment for XmlElementRef {}
252impl IndexedSequence for XmlElementRef {}
253
254impl AsRef<XmlFragmentRef> for XmlElementRef {
255 #[inline]
256 fn as_ref(&self) -> &XmlFragmentRef {
257 unsafe { std::mem::transmute(self) }
258 }
259}
260
261impl AsRef<ArrayRef> for XmlElementRef {
262 #[inline]
263 fn as_ref(&self) -> &ArrayRef {
264 unsafe { std::mem::transmute(self) }
265 }
266}
267
268impl XmlElementRef {
269 pub fn try_tag(&self) -> Option<&Arc<str>> {
271 if let TypeRef::XmlElement(tag) = &self.0.type_ref {
272 Some(tag)
273 } else {
274 None
276 }
277 }
278
279 pub fn tag(&self) -> &Arc<str> {
281 self.try_tag().expect("XmlElement tag was not defined")
282 }
283}
284
285impl GetString for XmlElementRef {
286 fn get_string<T: ReadTxn>(&self, txn: &T) -> String {
289 let tag: &str = self.tag();
290 let inner = self.0;
291 let mut s = String::new();
292 write!(&mut s, "<{}", tag).unwrap();
293 let attributes = Attributes(inner.entries(txn));
294 for (k, v) in attributes {
295 write!(&mut s, " {}=\"{}\"", k, v).unwrap();
296 }
297 write!(&mut s, ">").unwrap();
298 for i in inner.iter(txn) {
299 if !i.is_deleted() {
300 for content in i.content.get_content() {
301 write!(&mut s, "{}", content.to_string(txn)).unwrap();
302 }
303 }
304 }
305 write!(&mut s, "</{}>", tag).unwrap();
306 s
307 }
308}
309
310impl DeepObservable for XmlElementRef {}
311impl Observable for XmlElementRef {
312 type Event = XmlEvent;
313}
314
315impl AsRef<Branch> for XmlElementRef {
316 fn as_ref(&self) -> &Branch {
317 &self.0
318 }
319}
320
321impl Eq for XmlElementRef {}
322impl PartialEq for XmlElementRef {
323 fn eq(&self, other: &Self) -> bool {
324 self.0.id() == other.0.id()
325 }
326}
327
328impl From<BranchPtr> for XmlElementRef {
329 fn from(inner: BranchPtr) -> Self {
330 XmlElementRef(inner)
331 }
332}
333
334impl TryFrom<ItemPtr> for XmlElementRef {
335 type Error = ItemPtr;
336
337 fn try_from(value: ItemPtr) -> Result<Self, Self::Error> {
338 if let Some(branch) = value.clone().as_branch() {
339 Ok(Self::from(branch))
340 } else {
341 Err(value)
342 }
343 }
344}
345
346impl TryFrom<Out> for XmlElementRef {
347 type Error = Out;
348
349 fn try_from(value: Out) -> Result<Self, Self::Error> {
350 match value {
351 Out::YXmlElement(value) => Ok(value),
352 other => Err(other),
353 }
354 }
355}
356
357impl AsPrelim for XmlElementRef {
358 type Prelim = XmlElementPrelim;
359
360 fn as_prelim<T: ReadTxn>(&self, txn: &T) -> Self::Prelim {
361 let attributes: HashMap<Arc<str>, String> = self
362 .0
363 .map
364 .iter()
365 .flat_map(|(k, ptr)| {
366 if ptr.is_deleted() {
367 None
368 } else if let Some(value) = ptr.content.get_last() {
369 Some((k.clone(), value.to_string(txn)))
370 } else {
371 None
372 }
373 })
374 .collect();
375 let children: Vec<_> = self
376 .children(txn)
377 .map(|v| match v {
378 XmlOut::Element(v) => XmlIn::Element(v.as_prelim(txn)),
379 XmlOut::Fragment(v) => XmlIn::Fragment(v.as_prelim(txn)),
380 XmlOut::Text(v) => XmlIn::Text(v.as_prelim(txn)),
381 })
382 .collect();
383 XmlElementPrelim {
384 tag: self.tag().clone(),
385 attributes,
386 children,
387 }
388 }
389}
390
391#[derive(Debug, Clone, PartialEq)]
394pub struct XmlElementPrelim {
395 pub tag: Arc<str>,
396 pub attributes: HashMap<Arc<str>, String>,
397 pub children: Vec<XmlIn>,
398}
399
400impl XmlElementPrelim {
401 pub fn new<S, I>(tag: S, iter: I) -> Self
402 where
403 S: Into<Arc<str>>,
404 I: IntoIterator<Item = XmlIn>,
405 {
406 XmlElementPrelim {
407 tag: tag.into(),
408 attributes: HashMap::default(),
409 children: iter.into_iter().collect(),
410 }
411 }
412
413 pub fn empty<S>(tag: S) -> Self
414 where
415 S: Into<Arc<str>>,
416 {
417 XmlElementPrelim {
418 tag: tag.into(),
419 attributes: HashMap::default(),
420 children: Vec::default(),
421 }
422 }
423}
424
425impl XmlPrelim for XmlElementPrelim {}
426
427impl Prelim for XmlElementPrelim {
428 type Return = XmlElementRef;
429
430 fn into_content(self, _txn: &mut TransactionMut) -> (ItemContent, Option<Self>) {
431 let inner = Branch::new(TypeRef::XmlElement(self.tag.clone()));
432 (ItemContent::Type(inner), Some(self))
433 }
434
435 fn integrate(self, txn: &mut TransactionMut, inner_ref: BranchPtr) {
436 let xml = XmlElementRef::from(inner_ref);
437 for (key, value) in self.attributes {
438 xml.insert_attribute(txn, key, value);
439 }
440 for value in self.children {
441 xml.push_back(txn, value);
442 }
443 }
444}
445
446impl Into<EmbedPrelim<XmlElementPrelim>> for XmlElementPrelim {
447 #[inline]
448 fn into(self) -> EmbedPrelim<XmlElementPrelim> {
449 EmbedPrelim::Shared(self)
450 }
451}
452
453impl From<XmlElementPrelim> for In {
454 #[inline]
455 fn from(value: XmlElementPrelim) -> Self {
456 In::XmlElement(value)
457 }
458}
459
460#[repr(transparent)]
529#[derive(Debug, Clone)]
530pub struct XmlTextRef(BranchPtr);
531
532impl XmlTextRef {
533 pub(crate) fn get_string_fragment(
534 head: Option<ItemPtr>,
535 start: Option<&StickyIndex>,
536 end: Option<&StickyIndex>,
537 ) -> String {
538 let mut buf = String::new();
539 for d in diff_between(head, start, end, YChange::identity) {
540 let mut attrs = Vec::new();
541 if let Some(attributes) = d.attributes.as_ref() {
542 for (key, value) in attributes.iter() {
543 attrs.push((key, value));
544 }
545 attrs.sort_by(|x, y| x.0.cmp(y.0))
546 }
547
548 for (node, at) in attrs.iter() {
550 write!(buf, "<{}", node).unwrap();
551 if let Any::Map(at) = at {
552 for (k, v) in at.iter() {
553 write!(buf, " {}=\"{}\"", k, v).unwrap();
554 }
555 }
556 buf.push('>');
557 }
558
559 if let Out::Any(any) = d.insert {
561 write!(buf, "{}", any).unwrap();
562 }
563
564 attrs.reverse();
566 for (key, _) in attrs {
567 write!(buf, "</{}>", key).unwrap();
568 }
569 }
570 buf
571 }
572}
573
574impl SharedRef for XmlTextRef {}
575impl Xml for XmlTextRef {}
576impl Text for XmlTextRef {}
577impl IndexedSequence for XmlTextRef {}
578#[cfg(feature = "weak")]
579impl crate::Quotable for XmlTextRef {}
580
581impl AsRef<TextRef> for XmlTextRef {
582 #[inline]
583 fn as_ref(&self) -> &TextRef {
584 unsafe { std::mem::transmute(self) }
585 }
586}
587
588impl DeepObservable for XmlTextRef {}
589impl Observable for XmlTextRef {
590 type Event = XmlTextEvent;
591}
592
593impl GetString for XmlTextRef {
594 fn get_string<T: ReadTxn>(&self, _txn: &T) -> String {
595 XmlTextRef::get_string_fragment(self.0.start, None, None)
596 }
597}
598
599impl AsRef<Branch> for XmlTextRef {
600 fn as_ref(&self) -> &Branch {
601 &self.0
602 }
603}
604
605impl Eq for XmlTextRef {}
606impl PartialEq for XmlTextRef {
607 fn eq(&self, other: &Self) -> bool {
608 self.0.id() == other.0.id()
609 }
610}
611
612impl From<BranchPtr> for XmlTextRef {
613 fn from(inner: BranchPtr) -> Self {
614 XmlTextRef(inner)
615 }
616}
617
618impl TryFrom<ItemPtr> for XmlTextRef {
619 type Error = ItemPtr;
620
621 fn try_from(value: ItemPtr) -> Result<Self, Self::Error> {
622 if let Some(branch) = value.clone().as_branch() {
623 Ok(Self::from(branch))
624 } else {
625 Err(value)
626 }
627 }
628}
629
630impl TryFrom<Out> for XmlTextRef {
631 type Error = Out;
632
633 fn try_from(value: Out) -> Result<Self, Self::Error> {
634 match value {
635 Out::YXmlText(value) => Ok(value),
636 other => Err(other),
637 }
638 }
639}
640
641impl AsPrelim for XmlTextRef {
642 type Prelim = XmlDeltaPrelim;
643
644 fn as_prelim<T: ReadTxn>(&self, txn: &T) -> Self::Prelim {
645 let attributes: HashMap<Arc<str>, String> = self
646 .0
647 .map
648 .iter()
649 .flat_map(|(k, ptr)| {
650 if ptr.is_deleted() {
651 None
652 } else if let Some(value) = ptr.content.get_last() {
653 Some((k.clone(), value.to_string(txn)))
654 } else {
655 None
656 }
657 })
658 .collect();
659 let delta: Vec<Delta<In>> = self
660 .diff(txn, YChange::identity)
661 .into_iter()
662 .map(|diff| Delta::Inserted(diff.insert.as_prelim(txn), diff.attributes))
663 .collect();
664 XmlDeltaPrelim { attributes, delta }
665 }
666}
667
668impl DefaultPrelim for XmlTextRef {
669 type Prelim = XmlTextPrelim;
670
671 #[inline]
672 fn default_prelim() -> Self::Prelim {
673 XmlTextPrelim::default()
674 }
675}
676
677#[repr(transparent)]
680#[derive(Debug, Clone, PartialEq, Hash, Default)]
681pub struct XmlTextPrelim(String);
682
683impl Deref for XmlTextPrelim {
684 type Target = String;
685
686 #[inline]
687 fn deref(&self) -> &Self::Target {
688 &self.0
689 }
690}
691
692impl DerefMut for XmlTextPrelim {
693 #[inline]
694 fn deref_mut(&mut self) -> &mut Self::Target {
695 &mut self.0
696 }
697}
698
699impl XmlTextPrelim {
700 #[inline]
701 pub fn new<S: Into<String>>(str: S) -> Self {
702 XmlTextPrelim(str.into())
703 }
704}
705
706impl XmlPrelim for XmlTextPrelim {}
707
708impl Prelim for XmlTextPrelim {
709 type Return = XmlTextRef;
710
711 fn into_content(self, _txn: &mut TransactionMut) -> (ItemContent, Option<Self>) {
712 let inner = Branch::new(TypeRef::XmlText);
713 (ItemContent::Type(inner), Some(self))
714 }
715
716 fn integrate(self, txn: &mut TransactionMut, inner_ref: BranchPtr) {
717 if !self.is_empty() {
718 let text = XmlTextRef::from(inner_ref);
719 text.push(txn, &self.0);
720 }
721 }
722}
723
724impl Into<EmbedPrelim<XmlTextPrelim>> for XmlTextPrelim {
725 #[inline]
726 fn into(self) -> EmbedPrelim<XmlTextPrelim> {
727 EmbedPrelim::Shared(self)
728 }
729}
730
731impl From<XmlTextPrelim> for In {
732 #[inline]
733 fn from(value: XmlTextPrelim) -> Self {
734 In::XmlText(XmlDeltaPrelim::from(value))
735 }
736}
737
738#[derive(Debug, Clone, PartialEq, Default)]
739pub struct XmlDeltaPrelim {
740 pub attributes: HashMap<Arc<str>, String>,
741 pub delta: Vec<Delta<In>>,
742}
743
744impl Deref for XmlDeltaPrelim {
745 type Target = [Delta<In>];
746
747 #[inline]
748 fn deref(&self) -> &Self::Target {
749 &self.delta
750 }
751}
752
753impl Prelim for XmlDeltaPrelim {
754 type Return = XmlTextRef;
755
756 fn into_content(self, _txn: &mut TransactionMut) -> (ItemContent, Option<Self>) {
757 (ItemContent::Type(Branch::new(TypeRef::XmlText)), Some(self))
758 }
759
760 fn integrate(self, txn: &mut TransactionMut, inner_ref: BranchPtr) {
761 let text_ref = XmlTextRef::from(inner_ref);
762 for (key, value) in self.attributes {
763 text_ref.insert_attribute(txn, key, value);
764 }
765 text_ref.apply_delta(txn, self.delta);
766 }
767}
768
769impl From<XmlTextPrelim> for XmlDeltaPrelim {
770 fn from(value: XmlTextPrelim) -> Self {
771 XmlDeltaPrelim {
772 attributes: HashMap::default(),
773 delta: vec![Delta::Inserted(In::Any(Any::from(value.0)), None)],
774 }
775 }
776}
777
778impl From<XmlDeltaPrelim> for In {
779 #[inline]
780 fn from(value: XmlDeltaPrelim) -> Self {
781 In::XmlText(value)
782 }
783}
784
785#[repr(transparent)]
787#[derive(Debug, Clone)]
788pub struct XmlFragmentRef(BranchPtr);
789
790impl RootRef for XmlFragmentRef {
791 fn type_ref() -> TypeRef {
792 TypeRef::XmlFragment
793 }
794}
795impl SharedRef for XmlFragmentRef {}
796impl XmlFragment for XmlFragmentRef {}
797impl IndexedSequence for XmlFragmentRef {}
798
799impl XmlFragmentRef {
800 pub fn parent(&self) -> Option<XmlOut> {
801 let item = self.0.item?;
802 let parent = item.parent.as_branch()?;
803 XmlOut::try_from(*parent).ok()
804 }
805}
806
807impl AsRef<ArrayRef> for XmlFragmentRef {
808 #[inline]
809 fn as_ref(&self) -> &ArrayRef {
810 unsafe { std::mem::transmute(self) }
811 }
812}
813
814impl GetString for XmlFragmentRef {
815 fn get_string<T: ReadTxn>(&self, txn: &T) -> String {
818 let inner = self.0;
819 let mut s = String::new();
820 for i in inner.iter(txn) {
821 if !i.is_deleted() {
822 for content in i.content.get_content() {
823 write!(&mut s, "{}", content.to_string(txn)).unwrap();
824 }
825 }
826 }
827 s
828 }
829}
830
831impl DeepObservable for XmlFragmentRef {}
832impl Observable for XmlFragmentRef {
833 type Event = XmlEvent;
834}
835
836impl AsRef<Branch> for XmlFragmentRef {
837 fn as_ref(&self) -> &Branch {
838 self.0.deref()
839 }
840}
841
842impl Eq for XmlFragmentRef {}
843impl PartialEq for XmlFragmentRef {
844 fn eq(&self, other: &Self) -> bool {
845 self.0.id() == other.0.id()
846 }
847}
848
849impl From<BranchPtr> for XmlFragmentRef {
850 fn from(inner: BranchPtr) -> Self {
851 XmlFragmentRef(inner)
852 }
853}
854
855impl TryFrom<ItemPtr> for XmlFragmentRef {
856 type Error = ItemPtr;
857
858 fn try_from(value: ItemPtr) -> Result<Self, Self::Error> {
859 if let Some(branch) = value.clone().as_branch() {
860 Ok(Self::from(branch))
861 } else {
862 Err(value)
863 }
864 }
865}
866
867impl TryFrom<Out> for XmlFragmentRef {
868 type Error = Out;
869
870 fn try_from(value: Out) -> Result<Self, Self::Error> {
871 match value {
872 Out::YXmlFragment(value) => Ok(value),
873 other => Err(other),
874 }
875 }
876}
877
878impl AsPrelim for XmlFragmentRef {
879 type Prelim = XmlFragmentPrelim;
880
881 fn as_prelim<T: ReadTxn>(&self, txn: &T) -> Self::Prelim {
882 let children: Vec<_> = self
883 .children(txn)
884 .map(|v| match v {
885 XmlOut::Element(v) => XmlIn::from(v.as_prelim(txn)),
886 XmlOut::Fragment(v) => XmlIn::from(v.as_prelim(txn)),
887 XmlOut::Text(v) => XmlIn::from(v.as_prelim(txn)),
888 })
889 .collect();
890 XmlFragmentPrelim(children)
891 }
892}
893
894impl DefaultPrelim for XmlFragmentRef {
895 type Prelim = XmlFragmentPrelim;
896
897 #[inline]
898 fn default_prelim() -> Self::Prelim {
899 XmlFragmentPrelim::default()
900 }
901}
902
903#[derive(Debug, Clone, PartialEq, Default)]
906pub struct XmlFragmentPrelim(Vec<XmlIn>);
907
908impl XmlFragmentPrelim {
909 pub fn new<I, T>(iter: I) -> Self
910 where
911 I: IntoIterator<Item = XmlIn>,
912 {
913 XmlFragmentPrelim(iter.into_iter().collect())
914 }
915}
916
917impl Prelim for XmlFragmentPrelim {
918 type Return = XmlFragmentRef;
919
920 fn into_content(self, _txn: &mut TransactionMut) -> (ItemContent, Option<Self>) {
921 let inner = Branch::new(TypeRef::XmlFragment);
922 (ItemContent::Type(inner), Some(self))
923 }
924
925 fn integrate(self, txn: &mut TransactionMut, inner_ref: BranchPtr) {
926 let xml = XmlFragmentRef::from(inner_ref);
927 for value in self.0 {
928 xml.push_back(txn, value);
929 }
930 }
931}
932
933impl Into<EmbedPrelim<XmlFragmentPrelim>> for XmlFragmentPrelim {
934 #[inline]
935 fn into(self) -> EmbedPrelim<XmlFragmentPrelim> {
936 EmbedPrelim::Shared(self)
937 }
938}
939
940impl From<XmlFragmentPrelim> for In {
941 #[inline]
942 fn from(value: XmlFragmentPrelim) -> Self {
943 In::XmlFragment(value)
944 }
945}
946
947#[derive(Debug, Clone)]
949pub struct XmlHookRef(BranchPtr);
950
951impl Map for XmlHookRef {}
952
953impl ToJson for XmlHookRef {
954 fn to_json<T: ReadTxn>(&self, txn: &T) -> Any {
955 let map: &MapRef = self.as_ref();
956 map.to_json(txn)
957 }
958}
959
960impl AsRef<Branch> for XmlHookRef {
961 fn as_ref(&self) -> &Branch {
962 self.0.deref()
963 }
964}
965
966impl Eq for XmlHookRef {}
967impl PartialEq for XmlHookRef {
968 fn eq(&self, other: &Self) -> bool {
969 self.0.id() == other.0.id()
970 }
971}
972
973impl From<BranchPtr> for XmlHookRef {
974 fn from(inner: BranchPtr) -> Self {
975 XmlHookRef(inner)
976 }
977}
978
979impl AsRef<MapRef> for XmlHookRef {
980 #[inline]
981 fn as_ref(&self) -> &MapRef {
982 unsafe { std::mem::transmute(self) }
983 }
984}
985
986pub trait Xml: AsRef<Branch> {
987 fn parent(&self) -> Option<XmlOut> {
988 let item = self.as_ref().item?;
989 let parent = item.parent.as_branch()?;
990 XmlOut::try_from(*parent).ok()
991 }
992
993 fn remove_attribute<K>(&self, txn: &mut TransactionMut, attr_name: &K)
995 where
996 K: AsRef<str>,
997 {
998 self.as_ref().remove(txn, attr_name.as_ref());
999 }
1000
1001 fn insert_attribute<K, V>(&self, txn: &mut TransactionMut, attr_name: K, attr_value: V)
1003 where
1004 K: Into<Arc<str>>,
1005 V: Into<String>,
1006 {
1007 let key = attr_name.into();
1008 let value = attr_value.into();
1009 let pos = {
1010 let branch = self.as_ref();
1011 let left = branch.map.get(&key);
1012 ItemPosition {
1013 parent: BranchPtr::from(branch).into(),
1014 left: left.cloned(),
1015 right: None,
1016 index: 0,
1017 current_attrs: None,
1018 }
1019 };
1020
1021 txn.create_item(&pos, value, Some(key));
1022 }
1023
1024 fn get_attribute<T: ReadTxn>(&self, txn: &T, attr_name: &str) -> Option<String> {
1027 let branch = self.as_ref();
1028 let value = branch.get(txn, attr_name)?;
1029 Some(value.to_string(txn))
1030 }
1031
1032 fn attributes<'a, T: ReadTxn>(&'a self, txn: &'a T) -> Attributes<'a, &'a T, T> {
1035 Attributes(Entries::new(&self.as_ref().map, txn))
1036 }
1037
1038 fn siblings<'a, T: ReadTxn>(&self, txn: &'a T) -> Siblings<'a, T> {
1039 let ptr = BranchPtr::from(self.as_ref());
1040 Siblings::new(ptr.item, txn)
1041 }
1042}
1043
1044pub trait XmlFragment: AsRef<Branch> {
1045 fn first_child(&self) -> Option<XmlOut> {
1046 let first = self.as_ref().first()?;
1047 match &first.content {
1048 ItemContent::Type(c) => {
1049 let ptr = BranchPtr::from(c);
1050 XmlOut::try_from(ptr).ok()
1051 }
1052 _ => None,
1053 }
1054 }
1055
1056 fn children<'a, T: ReadTxn>(&self, txn: &'a T) -> XmlNodes<'a, T> {
1060 let iter = BlockIter::new(BranchPtr::from(self.as_ref()));
1061 XmlNodes::new(iter, txn)
1062 }
1063
1064 fn len<T: ReadTxn>(&self, _txn: &T) -> u32 {
1066 self.as_ref().len()
1067 }
1068
1069 fn insert<V>(&self, txn: &mut TransactionMut, index: u32, xml_node: V) -> V::Return
1075 where
1076 V: XmlPrelim,
1077 {
1078 let ptr = self.as_ref().insert_at(txn, index, xml_node).unwrap(); if let Ok(integrated) = V::Return::try_from(ptr) {
1080 integrated
1081 } else {
1082 panic!("Defect: inserted XML element returned primitive value block")
1083 }
1084 }
1085
1086 fn push_back<V>(&self, txn: &mut TransactionMut, xml_node: V) -> V::Return
1088 where
1089 V: XmlPrelim,
1090 {
1091 let len = self.len(txn);
1092 self.insert(txn, len, xml_node)
1093 }
1094
1095 fn push_front<V>(&self, txn: &mut TransactionMut, xml_node: V) -> V::Return
1097 where
1098 V: XmlPrelim,
1099 {
1100 self.insert(txn, 0, xml_node)
1101 }
1102
1103 fn remove(&self, txn: &mut TransactionMut, index: u32) {
1105 self.remove_range(txn, index, 1)
1106 }
1107
1108 fn remove_range(&self, txn: &mut TransactionMut, index: u32, len: u32) {
1113 let mut walker = BlockIter::new(BranchPtr::from(self.as_ref()));
1114 if walker.try_forward(txn, index) {
1115 walker.delete(txn, len)
1116 } else {
1117 panic!("Index {} is outside of the range of an array", index);
1118 }
1119 }
1120
1121 fn get<T: ReadTxn>(&self, _txn: &T, index: u32) -> Option<XmlOut> {
1124 let branch = self.as_ref();
1125 let (content, _) = branch.get_at(index)?;
1126 if let ItemContent::Type(inner) = content {
1127 let ptr: BranchPtr = inner.into();
1128 XmlOut::try_from(ptr).ok()
1129 } else {
1130 None
1131 }
1132 }
1133
1134 fn successors<'a, T: ReadTxn>(&'a self, txn: &'a T) -> TreeWalker<'a, &'a T, T> {
1175 TreeWalker::new(self.as_ref(), txn)
1176 }
1177}
1178
1179pub struct Attributes<'a, B, T>(Entries<'a, B, T>);
1181
1182impl<'a, B, T> Attributes<'a, B, T>
1183where
1184 B: Borrow<T>,
1185 T: ReadTxn,
1186{
1187 pub fn new(branch: &'a Branch, txn: B) -> Self {
1188 let entries = Entries::new(&branch.map, txn);
1189 Attributes(entries)
1190 }
1191}
1192
1193impl<'a, B, T> Iterator for Attributes<'a, B, T>
1194where
1195 B: Borrow<T>,
1196 T: ReadTxn,
1197{
1198 type Item = (&'a str, String);
1199
1200 fn next(&mut self) -> Option<Self::Item> {
1201 let (key, block) = self.0.next()?;
1202 let txn = self.0.txn.borrow();
1203 let value = block
1204 .content
1205 .get_last()
1206 .map(|v| v.to_string(txn))
1207 .unwrap_or(String::default());
1208 Some((key.as_ref(), value))
1209 }
1210}
1211
1212pub struct XmlNodes<'a, T> {
1213 iter: BlockIter,
1214 txn: &'a T,
1215}
1216
1217impl<'a, T: ReadTxn> XmlNodes<'a, T> {
1218 fn new(iter: BlockIter, txn: &'a T) -> Self {
1219 XmlNodes { iter, txn }
1220 }
1221}
1222
1223impl<'a, T: ReadTxn> Iterator for XmlNodes<'a, T> {
1224 type Item = XmlOut;
1225
1226 fn next(&mut self) -> Option<Self::Item> {
1227 let value = self.iter.read_value(self.txn)?;
1228 XmlOut::try_from(value).ok()
1229 }
1230}
1231
1232pub struct TreeWalker<'a, B, T> {
1234 current: Option<&'a Item>,
1235 root: TypePtr,
1236 first_call: bool,
1237 _txn: B,
1238 _marker: PhantomData<T>,
1239}
1240
1241impl<'a, B, T: ReadTxn> TreeWalker<'a, B, T>
1242where
1243 B: Borrow<T>,
1244 T: ReadTxn,
1245{
1246 pub fn new(root: &'a Branch, txn: B) -> Self {
1247 TreeWalker {
1248 current: root.start.as_deref(),
1249 root: TypePtr::Branch(BranchPtr::from(root)),
1250 first_call: true,
1251 _txn: txn,
1252 _marker: PhantomData::default(),
1253 }
1254 }
1255}
1256
1257impl<'a, B, T: ReadTxn> Iterator for TreeWalker<'a, B, T>
1258where
1259 B: Borrow<T>,
1260 T: ReadTxn,
1261{
1262 type Item = XmlOut;
1263
1264 fn next(&mut self) -> Option<Self::Item> {
1266 fn try_descend(item: &Item) -> Option<&Item> {
1267 if let ItemContent::Type(t) = &item.content {
1268 let inner = t.as_ref();
1269 match inner.type_ref() {
1270 TypeRef::XmlElement(_) | TypeRef::XmlFragment if !item.is_deleted() => {
1271 return inner.start.as_deref();
1272 }
1273 _ => { }
1274 }
1275 }
1276
1277 None
1278 }
1279
1280 let mut result = None;
1281 let mut n = self.current.take();
1282 if let Some(current) = n {
1283 if !self.first_call || current.is_deleted() {
1284 while {
1285 if let Some(current) = n {
1286 if let Some(ptr) = try_descend(current) {
1287 n = Some(ptr);
1289 } else {
1290 while let Some(current) = n {
1292 if let Some(right) = current.right.as_ref() {
1293 n = Some(right);
1294 break;
1295 } else if current.parent == self.root {
1296 n = None;
1297 } else {
1298 let ptr = current.parent.as_branch().unwrap();
1299 n = ptr.item.as_deref();
1300 }
1301 }
1302 }
1303 }
1304 if let Some(current) = n {
1305 current.is_deleted()
1306 } else {
1307 false
1308 }
1309 } {}
1310 }
1311 self.first_call = false;
1312 self.current = n;
1313 }
1314 if let Some(current) = self.current {
1315 if let ItemContent::Type(t) = ¤t.content {
1316 result = XmlOut::try_from(BranchPtr::from(t)).ok();
1317 }
1318 }
1319 result
1320 }
1321}
1322
1323pub struct XmlTextEvent {
1325 pub(crate) current_target: BranchPtr,
1326 target: XmlTextRef,
1327 delta: UnsafeCell<Option<Vec<Delta>>>,
1328 keys: UnsafeCell<Result<HashMap<Arc<str>, EntryChange>, HashSet<Option<Arc<str>>>>>,
1329}
1330
1331impl XmlTextEvent {
1332 pub(crate) fn new(branch_ref: BranchPtr, key_changes: HashSet<Option<Arc<str>>>) -> Self {
1333 let current_target = branch_ref.clone();
1334 let target = XmlTextRef::from(branch_ref);
1335 XmlTextEvent {
1336 target,
1337 current_target,
1338 delta: UnsafeCell::new(None),
1339 keys: UnsafeCell::new(Err(key_changes)),
1340 }
1341 }
1342
1343 pub fn target(&self) -> &XmlTextRef {
1345 &self.target
1346 }
1347
1348 pub fn path(&self) -> Path {
1350 Branch::path(self.current_target, self.target.0)
1351 }
1352
1353 pub fn delta(&self, txn: &TransactionMut) -> &[Delta] {
1356 let delta = unsafe { self.delta.get().as_mut().unwrap() };
1357 delta
1358 .get_or_insert_with(|| TextEvent::get_delta(self.target.0, txn))
1359 .as_slice()
1360 }
1361
1362 pub fn keys(&self, txn: &TransactionMut) -> &HashMap<Arc<str>, EntryChange> {
1365 let keys = unsafe { self.keys.get().as_mut().unwrap() };
1366
1367 match keys {
1368 Ok(keys) => {
1369 return keys;
1370 }
1371 Err(subs) => {
1372 let subs = event_keys(txn, self.target.0, subs);
1373 *keys = Ok(subs);
1374 if let Ok(keys) = keys {
1375 keys
1376 } else {
1377 panic!("Defect: should not happen");
1378 }
1379 }
1380 }
1381 }
1382}
1383
1384pub struct Siblings<'a, T> {
1385 current: Option<ItemPtr>,
1386 _txn: &'a T,
1387}
1388
1389impl<'a, T> Siblings<'a, T> {
1390 fn new(current: Option<ItemPtr>, txn: &'a T) -> Self {
1391 Siblings { current, _txn: txn }
1392 }
1393}
1394
1395impl<'a, T> Iterator for Siblings<'a, T> {
1396 type Item = XmlOut;
1397
1398 fn next(&mut self) -> Option<Self::Item> {
1399 while let Some(item) = self.current.as_deref() {
1400 self.current = item.right;
1401 if let Some(right) = self.current.as_deref() {
1402 if !right.is_deleted() {
1403 if let ItemContent::Type(inner) = &right.content {
1404 let ptr = BranchPtr::from(inner);
1405 return XmlOut::try_from(ptr).ok();
1406 }
1407 }
1408 }
1409 }
1410
1411 None
1412 }
1413}
1414
1415impl<'a, T> DoubleEndedIterator for Siblings<'a, T> {
1416 fn next_back(&mut self) -> Option<Self::Item> {
1417 while let Some(item) = self.current.as_deref() {
1418 self.current = item.left;
1419 if let Some(left) = self.current.as_deref() {
1420 if !left.is_deleted() {
1421 if let ItemContent::Type(inner) = &left.content {
1422 let ptr = BranchPtr::from(inner);
1423 return XmlOut::try_from(ptr).ok();
1424 }
1425 }
1426 }
1427 }
1428
1429 None
1430 }
1431}
1432
1433pub struct XmlEvent {
1435 pub(crate) current_target: BranchPtr,
1436 target: XmlOut,
1437 change_set: UnsafeCell<Option<Box<ChangeSet<Change>>>>,
1438 keys: UnsafeCell<Result<HashMap<Arc<str>, EntryChange>, HashSet<Option<Arc<str>>>>>,
1439 children_changed: bool,
1440}
1441
1442impl XmlEvent {
1443 pub(crate) fn new(branch_ref: BranchPtr, key_changes: HashSet<Option<Arc<str>>>) -> Self {
1444 let current_target = branch_ref.clone();
1445 let children_changed = key_changes.iter().any(Option::is_none);
1446 XmlEvent {
1447 target: XmlOut::try_from(branch_ref).unwrap(),
1448 current_target,
1449 change_set: UnsafeCell::new(None),
1450 keys: UnsafeCell::new(Err(key_changes)),
1451 children_changed,
1452 }
1453 }
1454
1455 pub fn children_changed(&self) -> bool {
1457 self.children_changed
1458 }
1459
1460 pub fn target(&self) -> &XmlOut {
1462 &self.target
1463 }
1464
1465 pub fn path(&self) -> Path {
1467 Branch::path(self.current_target, self.target.as_ptr())
1468 }
1469
1470 pub fn delta(&self, txn: &TransactionMut) -> &[Change] {
1473 self.changes(txn).delta.as_slice()
1474 }
1475
1476 pub fn added(&self, txn: &TransactionMut) -> &HashSet<ID> {
1479 &self.changes(txn).added
1480 }
1481
1482 pub fn deleted(&self, txn: &TransactionMut) -> &HashSet<ID> {
1485 &self.changes(txn).deleted
1486 }
1487
1488 pub fn keys(&self, txn: &TransactionMut) -> &HashMap<Arc<str>, EntryChange> {
1491 let keys = unsafe { self.keys.get().as_mut().unwrap() };
1492
1493 match keys {
1494 Ok(keys) => keys,
1495 Err(subs) => {
1496 let subs = event_keys(txn, self.target.as_ptr(), subs);
1497 *keys = Ok(subs);
1498 if let Ok(keys) = keys {
1499 keys
1500 } else {
1501 panic!("Defect: should not happen");
1502 }
1503 }
1504 }
1505 }
1506
1507 fn changes(&self, txn: &TransactionMut) -> &ChangeSet<Change> {
1508 let change_set = unsafe { self.change_set.get().as_mut().unwrap() };
1509 change_set
1510 .get_or_insert_with(|| Box::new(event_change_set(txn, self.target.as_ptr().start)))
1511 }
1512}
1513
1514#[cfg(test)]
1515mod test {
1516 use std::collections::HashMap;
1517 use std::sync::Arc;
1518
1519 use arc_swap::ArcSwapOption;
1520
1521 use crate::test_utils::exchange_updates;
1522 use crate::transaction::ReadTxn;
1523 use crate::types::xml::{Xml, XmlFragment, XmlOut};
1524 use crate::types::{Attrs, Change, EntryChange, Out};
1525 use crate::updates::decoder::Decode;
1526 use crate::updates::encoder::{Encoder, EncoderV1};
1527 use crate::{
1528 Any, Doc, GetString, Observable, SharedRef, StateVector, Text, Transact, Update,
1529 XmlElementPrelim, XmlTextPrelim, XmlTextRef,
1530 };
1531
1532 #[test]
1533 fn insert_attribute() {
1534 let d1 = Doc::with_client_id(1);
1535 let f = d1.get_or_insert_xml_fragment("xml");
1536 let mut t1 = d1.transact_mut();
1537 let xml1 = f.push_back(&mut t1, XmlElementPrelim::empty("div"));
1538 xml1.insert_attribute(&mut t1, "height", 10.to_string());
1539 assert_eq!(xml1.get_attribute(&t1, "height"), Some("10".to_string()));
1540
1541 let d2 = Doc::with_client_id(1);
1542 let f = d2.get_or_insert_xml_fragment("xml");
1543 let mut t2 = d2.transact_mut();
1544 let xml2 = f.push_back(&mut t2, XmlElementPrelim::empty("div"));
1545 let u = t1.encode_state_as_update_v1(&StateVector::default());
1546 let u = Update::decode_v1(u.as_slice()).unwrap();
1547 t2.apply_update(u).unwrap();
1548 assert_eq!(xml2.get_attribute(&t2, "height"), Some("10".to_string()));
1549 }
1550
1551 #[test]
1552 fn tree_walker() {
1553 let doc = Doc::with_client_id(1);
1554 let root = doc.get_or_insert_xml_fragment("xml");
1555 let mut txn = doc.transact_mut();
1556 let p1 = root.push_back(&mut txn, XmlElementPrelim::empty("p"));
1564 p1.push_back(&mut txn, XmlTextPrelim::new(""));
1565 p1.push_back(&mut txn, XmlTextPrelim::new(""));
1566 let p2 = root.push_back(&mut txn, XmlElementPrelim::empty("p"));
1567 root.push_back(&mut txn, XmlElementPrelim::empty("img"));
1568
1569 let all_paragraphs = root.successors(&txn).filter_map(|n| match n {
1570 XmlOut::Element(e) if e.tag() == &"p".into() => Some(e),
1571 _ => None,
1572 });
1573 let actual: Vec<_> = all_paragraphs.collect();
1574
1575 assert_eq!(
1576 actual.len(),
1577 2,
1578 "query selector should found two paragraphs"
1579 );
1580 assert_eq!(
1581 actual[0].hook(),
1582 p1.hook(),
1583 "query selector found 1st paragraph"
1584 );
1585 assert_eq!(
1586 actual[1].hook(),
1587 p2.hook(),
1588 "query selector found 2nd paragraph"
1589 );
1590 }
1591
1592 #[test]
1593 fn text_attributes() {
1594 let doc = Doc::with_client_id(1);
1595 let f = doc.get_or_insert_xml_fragment("test");
1596 let mut txn = doc.transact_mut();
1597 let txt = f.push_back(&mut txn, XmlTextPrelim::new(""));
1598 txt.insert_attribute(&mut txn, "test", 42.to_string());
1599
1600 assert_eq!(txt.get_attribute(&txn, "test"), Some("42".to_string()));
1601 let actual: Vec<_> = txt.attributes(&txn).collect();
1602 assert_eq!(actual, vec![("test", "42".to_string())]);
1603 }
1604
1605 #[test]
1606 fn siblings() {
1607 let doc = Doc::with_client_id(1);
1608 let root = doc.get_or_insert_xml_fragment("root");
1609 let mut txn = doc.transact_mut();
1610 let first = root.push_back(&mut txn, XmlTextPrelim::new("hello"));
1611 let second = root.push_back(&mut txn, XmlElementPrelim::empty("p"));
1612
1613 assert_eq!(
1614 &first.siblings(&txn).next().unwrap().id(),
1615 second.hook().id(),
1616 "first.next_sibling should point to second"
1617 );
1618 assert_eq!(
1619 &second.siblings(&txn).next_back().unwrap().id(),
1620 first.hook().id(),
1621 "second.prev_sibling should point to first"
1622 );
1623 assert_eq!(
1624 &first.parent().unwrap().id(),
1625 root.hook().id(),
1626 "first.parent should point to root"
1627 );
1628 assert!(root.parent().is_none(), "root parent should not exist");
1629 assert_eq!(
1630 &root.first_child().unwrap().id(),
1631 first.hook().id(),
1632 "root.first_child should point to first"
1633 );
1634 }
1635
1636 #[test]
1637 fn serialization() {
1638 let d1 = Doc::with_client_id(1);
1639 let r1 = d1.get_or_insert_xml_fragment("root");
1640 let mut t1 = d1.transact_mut();
1641 let _first = r1.push_back(&mut t1, XmlTextPrelim::new("hello"));
1642 r1.push_back(&mut t1, XmlElementPrelim::empty("p"));
1643
1644 let expected = "hello<p></p>";
1645 assert_eq!(r1.get_string(&t1), expected);
1646
1647 let u1 = t1.encode_state_as_update_v1(&StateVector::default());
1648
1649 let d2 = Doc::with_client_id(2);
1650 let r2 = d2.get_or_insert_xml_fragment("root");
1651 let mut t2 = d2.transact_mut();
1652
1653 let u1 = Update::decode_v1(u1.as_slice()).unwrap();
1654 t2.apply_update(u1).unwrap();
1655 assert_eq!(r2.get_string(&t2), expected);
1656 }
1657
1658 #[test]
1659 fn serialization_compatibility() {
1660 let d1 = Doc::with_client_id(1);
1661 let r1 = d1.get_or_insert_xml_fragment("root");
1662 let mut t1 = d1.transact_mut();
1663 let _first = r1.push_back(&mut t1, XmlTextPrelim::new("hello"));
1664 r1.push_back(&mut t1, XmlElementPrelim::empty("p"));
1665
1666 let expected = &[
1679 1, 3, 1, 0, 7, 1, 4, 114, 111, 111, 116, 6, 4, 0, 1, 0, 5, 104, 101, 108, 108, 111,
1680 135, 1, 0, 3, 1, 112, 0,
1681 ];
1682 let u1 = t1.encode_state_as_update_v1(&StateVector::default());
1683 assert_eq!(u1.as_slice(), expected);
1684 }
1685
1686 #[test]
1687 fn event_observers() {
1688 let d1 = Doc::with_client_id(1);
1689 let f = d1.get_or_insert_xml_fragment("xml");
1690 let xml = f.insert(&mut d1.transact_mut(), 0, XmlElementPrelim::empty("test"));
1691
1692 let d2 = Doc::with_client_id(2);
1693 let f = d2.get_or_insert_xml_fragment("xml");
1694 exchange_updates(&[&d1, &d2]);
1695 let xml2 = f
1696 .get(&d2.transact(), 0)
1697 .unwrap()
1698 .into_xml_element()
1699 .unwrap();
1700
1701 let attributes = Arc::new(ArcSwapOption::default());
1702 let nodes = Arc::new(ArcSwapOption::default());
1703 let attributes_c = attributes.clone();
1704 let nodes_c = nodes.clone();
1705 let _sub = xml.observe(move |txn, e| {
1706 attributes_c.store(Some(Arc::new(e.keys(txn).clone())));
1707 nodes_c.store(Some(Arc::new(e.delta(txn).to_vec())));
1708 });
1709
1710 {
1712 let mut txn = d1.transact_mut();
1713 xml.insert_attribute(&mut txn, "key1", "value1");
1714 xml.insert_attribute(&mut txn, "key2", "value2");
1715 }
1716 assert!(nodes.swap(None).unwrap().is_empty());
1717 assert_eq!(
1718 attributes.swap(None),
1719 Some(Arc::new(HashMap::from([
1720 (
1721 "key1".into(),
1722 EntryChange::Inserted(Any::String("value1".into()).into())
1723 ),
1724 (
1725 "key2".into(),
1726 EntryChange::Inserted(Any::String("value2".into()).into())
1727 )
1728 ])))
1729 );
1730
1731 {
1733 let mut txn = d1.transact_mut();
1734 xml.insert_attribute(&mut txn, "key1", "value11");
1735 xml.remove_attribute(&mut txn, &"key2");
1736 }
1737 assert!(nodes.swap(None).unwrap().is_empty());
1738 assert_eq!(
1739 attributes.swap(None),
1740 Some(Arc::new(HashMap::from([
1741 (
1742 "key1".into(),
1743 EntryChange::Updated(
1744 Any::String("value1".into()).into(),
1745 Any::String("value11".into()).into()
1746 )
1747 ),
1748 (
1749 "key2".into(),
1750 EntryChange::Removed(Any::String("value2".into()).into())
1751 )
1752 ])))
1753 );
1754
1755 let (nested_txt, nested_xml) = {
1757 let mut txn = d1.transact_mut();
1758 let txt = xml.insert(&mut txn, 0, XmlTextPrelim::new(""));
1759 let xml2 = xml.insert(&mut txn, 1, XmlElementPrelim::empty("div"));
1760 (txt, xml2)
1761 };
1762 assert_eq!(
1763 nodes.swap(None),
1764 Some(Arc::new(vec![Change::Added(vec![
1765 Out::YXmlText(nested_txt.clone()),
1766 Out::YXmlElement(nested_xml.clone())
1767 ])]))
1768 );
1769 assert_eq!(attributes.swap(None), Some(HashMap::new().into()));
1770
1771 let nested_xml2 = {
1773 let mut txn = d1.transact_mut();
1774 xml.remove_range(&mut txn, 1, 1);
1775 xml.insert(&mut txn, 1, XmlElementPrelim::empty("p"))
1776 };
1777 assert_eq!(
1778 nodes.swap(None),
1779 Some(Arc::new(vec![
1780 Change::Retain(1),
1781 Change::Added(vec![Out::YXmlElement(nested_xml2.clone())]),
1782 Change::Removed(1),
1783 ]))
1784 );
1785 assert_eq!(attributes.swap(None), Some(HashMap::new().into()));
1786
1787 let attributes = Arc::new(ArcSwapOption::default());
1789 let nodes = Arc::new(ArcSwapOption::default());
1790 let attributes_c = attributes.clone();
1791 let nodes_c = nodes.clone();
1792 let _sub = xml2.observe(move |txn, e| {
1793 attributes_c.store(Some(Arc::new(e.keys(txn).clone())));
1794 nodes_c.store(Some(Arc::new(e.delta(txn).to_vec())));
1795 });
1796
1797 {
1798 let t1 = d1.transact_mut();
1799 let mut t2 = d2.transact_mut();
1800 let sv = t2.state_vector();
1801 let mut encoder = EncoderV1::new();
1802 t1.encode_diff(&sv, &mut encoder);
1803 let update = Update::decode_v1(encoder.to_vec().as_slice()).unwrap();
1804 t2.apply_update(update).unwrap();
1805 }
1806 assert_eq!(
1807 nodes.swap(None),
1808 Some(Arc::new(vec![Change::Added(vec![
1809 Out::YXmlText(nested_txt),
1810 Out::YXmlElement(nested_xml2)
1811 ])]))
1812 );
1813 assert_eq!(
1814 attributes.swap(None),
1815 Some(Arc::new(HashMap::from([(
1816 "key1".into(),
1817 EntryChange::Inserted(Any::String("value11".into()).into())
1818 )])))
1819 );
1820 }
1821
1822 #[test]
1823 fn xml_to_string() {
1824 let doc = Doc::new();
1825 let f = doc.get_or_insert_xml_fragment("test");
1826 let mut txn = doc.transact_mut();
1827 let div = f.push_back(&mut txn, XmlElementPrelim::empty("div"));
1828 div.insert_attribute(&mut txn, "class", "t-button");
1829 let text = div.push_back(&mut txn, XmlTextPrelim::new("hello world"));
1830 text.format(
1831 &mut txn,
1832 6,
1833 5,
1834 Attrs::from([(
1835 "a".into(),
1836 HashMap::from([("href".into(), "http://domain.org")]).into(),
1837 )]),
1838 );
1839 drop(txn);
1840
1841 let str = f.get_string(&doc.transact());
1842 assert_eq!(
1843 str.as_str(),
1844 "<div class=\"t-button\">hello <a href=\"http://domain.org\">world</a></div>"
1845 )
1846 }
1847
1848 #[test]
1849 fn xml_to_string_2() {
1850 let doc = Doc::new();
1851 let f = doc.get_or_insert_xml_fragment("article");
1852 let xml = f.insert(&mut doc.transact_mut(), 0, XmlTextPrelim::new(""));
1853 let mut txn = doc.transact_mut();
1854
1855 let bold = Attrs::from([("b".into(), true.into())]);
1856 let italic = Attrs::from([("i".into(), true.into())]);
1857
1858 xml.insert(&mut txn, 0, "hello ");
1859 xml.insert_with_attributes(&mut txn, 6, "world", italic);
1860 xml.format(&mut txn, 0, 5, bold);
1861
1862 assert_eq!(xml.get_string(&txn), "<b>hello</b> <i>world</i>");
1863
1864 let remove_italic = Attrs::from([("i".into(), Any::Null)]);
1865 xml.format(&mut txn, 6, 5, remove_italic);
1866
1867 assert_eq!(xml.get_string(&txn), "<b>hello</b> world");
1868 }
1869
1870 #[test]
1871 fn format_attributes_decode_compatibility_v1() {
1872 let data = &[
1873 1, 6, 1, 0, 6, 1, 4, 116, 101, 115, 116, 1, 105, 4, 116, 114, 117, 101, 132, 1, 0, 6,
1874 104, 101, 108, 108, 111, 32, 132, 1, 6, 5, 119, 111, 114, 108, 100, 134, 1, 11, 1, 105,
1875 4, 110, 117, 108, 108, 198, 1, 6, 1, 7, 1, 98, 4, 116, 114, 117, 101, 134, 1, 12, 1,
1876 98, 4, 110, 117, 108, 108, 0,
1877 ];
1878 let update = Update::decode_v1(data).unwrap();
1879 let doc = Doc::new();
1880 let txt = doc.get_or_insert_text("test");
1881 let txt: &XmlTextRef = txt.as_ref();
1882 let mut txn = doc.transact_mut();
1883
1884 txn.apply_update(update).unwrap();
1885 assert_eq!(txt.get_string(&txn), "<i>hello </i><b><i>world</i></b>");
1886
1887 let actual = txn.encode_state_as_update_v1(&StateVector::default());
1888 assert_eq!(actual, data);
1889 }
1890
1891 #[test]
1892 fn format_attributes_decode_compatibility_v2() {
1893 let data = &[
1894 0, 3, 0, 3, 1, 2, 65, 5, 5, 0, 12, 10, 74, 12, 1, 14, 9, 6, 0, 132, 1, 134, 0, 198, 0,
1895 134, 26, 19, 116, 101, 115, 116, 105, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108,
1896 100, 105, 98, 98, 4, 1, 6, 5, 65, 1, 1, 1, 0, 0, 1, 6, 0, 120, 126, 120, 126, 0,
1897 ];
1898 let update = Update::decode_v2(data).unwrap();
1899 let doc = Doc::new();
1900 let txt = doc.get_or_insert_text("test");
1901 let txt: &XmlTextRef = txt.as_ref();
1902 let mut txn = doc.transact_mut();
1903
1904 txn.apply_update(update).unwrap();
1905 assert_eq!(txt.get_string(&txn), "<i>hello </i><b><i>world</i></b>");
1906
1907 let actual = txn.encode_state_as_update_v2(&StateVector::default());
1908 assert_eq!(actual, data);
1909 }
1910}