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, key: K, value: V) -> V::Return
1003 where
1004 K: Into<Arc<str>>,
1005 V: Prelim,
1006 {
1007 let key = key.into();
1008 let pos = {
1009 let inner = self.as_ref();
1010 let left = inner.map.get(&key);
1011 ItemPosition {
1012 parent: BranchPtr::from(inner).into(),
1013 left: left.cloned(),
1014 right: None,
1015 index: 0,
1016 current_attrs: None,
1017 }
1018 };
1019
1020 let ptr = txn
1021 .create_item(&pos, value, Some(key))
1022 .expect("Cannot insert empty value");
1023 if let Ok(integrated) = ptr.try_into() {
1024 integrated
1025 } else {
1026 panic!("Defect: unexpected integrated type")
1027 }
1028 }
1029
1030 fn get_attribute<T: ReadTxn>(&self, txn: &T, attr_name: &str) -> Option<Out> {
1033 let branch = self.as_ref();
1034 branch.get(txn, attr_name)
1035 }
1036
1037 fn attributes<'a, T: ReadTxn>(&'a self, txn: &'a T) -> Attributes<'a, &'a T, T> {
1040 Attributes(Entries::new(&self.as_ref().map, txn))
1041 }
1042
1043 fn siblings<'a, T: ReadTxn>(&self, txn: &'a T) -> Siblings<'a, T> {
1044 let ptr = BranchPtr::from(self.as_ref());
1045 Siblings::new(ptr.item, txn)
1046 }
1047}
1048
1049pub trait XmlFragment: AsRef<Branch> {
1050 fn first_child(&self) -> Option<XmlOut> {
1051 let first = self.as_ref().first()?;
1052 match &first.content {
1053 ItemContent::Type(c) => {
1054 let ptr = BranchPtr::from(c);
1055 XmlOut::try_from(ptr).ok()
1056 }
1057 _ => None,
1058 }
1059 }
1060
1061 fn children<'a, T: ReadTxn>(&self, txn: &'a T) -> XmlNodes<'a, T> {
1065 let iter = BlockIter::new(BranchPtr::from(self.as_ref()));
1066 XmlNodes::new(iter, txn)
1067 }
1068
1069 fn len<T: ReadTxn>(&self, _txn: &T) -> u32 {
1071 self.as_ref().len()
1072 }
1073
1074 fn insert<V>(&self, txn: &mut TransactionMut, index: u32, xml_node: V) -> V::Return
1080 where
1081 V: XmlPrelim,
1082 {
1083 let ptr = self.as_ref().insert_at(txn, index, xml_node).unwrap(); if let Ok(integrated) = V::Return::try_from(ptr) {
1085 integrated
1086 } else {
1087 panic!("Defect: inserted XML element returned primitive value block")
1088 }
1089 }
1090
1091 fn push_back<V>(&self, txn: &mut TransactionMut, xml_node: V) -> V::Return
1093 where
1094 V: XmlPrelim,
1095 {
1096 let len = self.len(txn);
1097 self.insert(txn, len, xml_node)
1098 }
1099
1100 fn push_front<V>(&self, txn: &mut TransactionMut, xml_node: V) -> V::Return
1102 where
1103 V: XmlPrelim,
1104 {
1105 self.insert(txn, 0, xml_node)
1106 }
1107
1108 fn remove(&self, txn: &mut TransactionMut, index: u32) {
1110 self.remove_range(txn, index, 1)
1111 }
1112
1113 fn remove_range(&self, txn: &mut TransactionMut, index: u32, len: u32) {
1118 let mut walker = BlockIter::new(BranchPtr::from(self.as_ref()));
1119 if walker.try_forward(txn, index) {
1120 walker.delete(txn, len)
1121 } else {
1122 panic!("Index {} is outside of the range of an array", index);
1123 }
1124 }
1125
1126 fn get<T: ReadTxn>(&self, _txn: &T, index: u32) -> Option<XmlOut> {
1129 let branch = self.as_ref();
1130 let (content, _) = branch.get_at(index)?;
1131 if let ItemContent::Type(inner) = content {
1132 let ptr: BranchPtr = inner.into();
1133 XmlOut::try_from(ptr).ok()
1134 } else {
1135 None
1136 }
1137 }
1138
1139 fn successors<'a, T: ReadTxn>(&'a self, txn: &'a T) -> TreeWalker<'a, &'a T, T> {
1180 TreeWalker::new(self.as_ref(), txn)
1181 }
1182}
1183
1184pub struct Attributes<'a, B, T>(Entries<'a, B, T>);
1186
1187impl<'a, B, T> Attributes<'a, B, T>
1188where
1189 B: Borrow<T>,
1190 T: ReadTxn,
1191{
1192 pub fn new(branch: &'a Branch, txn: B) -> Self {
1193 let entries = Entries::new(&branch.map, txn);
1194 Attributes(entries)
1195 }
1196}
1197
1198impl<'a, B, T> Iterator for Attributes<'a, B, T>
1199where
1200 B: Borrow<T>,
1201 T: ReadTxn,
1202{
1203 type Item = (&'a str, Out);
1204
1205 fn next(&mut self) -> Option<Self::Item> {
1206 let (key, block) = self.0.next()?;
1207 match block.content.get_last() {
1208 Some(value) => Some((key.as_ref(), value)),
1209 None => self.next(),
1210 }
1211 }
1212}
1213
1214pub struct XmlNodes<'a, T> {
1215 iter: BlockIter,
1216 txn: &'a T,
1217}
1218
1219impl<'a, T: ReadTxn> XmlNodes<'a, T> {
1220 fn new(iter: BlockIter, txn: &'a T) -> Self {
1221 XmlNodes { iter, txn }
1222 }
1223}
1224
1225impl<'a, T: ReadTxn> Iterator for XmlNodes<'a, T> {
1226 type Item = XmlOut;
1227
1228 fn next(&mut self) -> Option<Self::Item> {
1229 let value = self.iter.read_value(self.txn)?;
1230 XmlOut::try_from(value).ok()
1231 }
1232}
1233
1234pub struct TreeWalker<'a, B, T> {
1236 current: Option<&'a Item>,
1237 root: TypePtr,
1238 first_call: bool,
1239 _txn: B,
1240 _marker: PhantomData<T>,
1241}
1242
1243impl<'a, B, T: ReadTxn> TreeWalker<'a, B, T>
1244where
1245 B: Borrow<T>,
1246 T: ReadTxn,
1247{
1248 pub fn new(root: &'a Branch, txn: B) -> Self {
1249 TreeWalker {
1250 current: root.start.as_deref(),
1251 root: TypePtr::Branch(BranchPtr::from(root)),
1252 first_call: true,
1253 _txn: txn,
1254 _marker: PhantomData::default(),
1255 }
1256 }
1257}
1258
1259impl<'a, B, T: ReadTxn> Iterator for TreeWalker<'a, B, T>
1260where
1261 B: Borrow<T>,
1262 T: ReadTxn,
1263{
1264 type Item = XmlOut;
1265
1266 fn next(&mut self) -> Option<Self::Item> {
1268 fn try_descend(item: &Item) -> Option<&Item> {
1269 if let ItemContent::Type(t) = &item.content {
1270 let inner = t.as_ref();
1271 match inner.type_ref() {
1272 TypeRef::XmlElement(_) | TypeRef::XmlFragment if !item.is_deleted() => {
1273 return inner.start.as_deref();
1274 }
1275 _ => { }
1276 }
1277 }
1278
1279 None
1280 }
1281
1282 let mut result = None;
1283 let mut n = self.current.take();
1284 if let Some(current) = n {
1285 if !self.first_call || current.is_deleted() {
1286 while {
1287 if let Some(current) = n {
1288 if let Some(ptr) = try_descend(current) {
1289 n = Some(ptr);
1291 } else {
1292 while let Some(current) = n {
1294 if let Some(right) = current.right.as_ref() {
1295 n = Some(right);
1296 break;
1297 } else if current.parent == self.root {
1298 n = None;
1299 } else {
1300 let ptr = current.parent.as_branch().unwrap();
1301 n = ptr.item.as_deref();
1302 }
1303 }
1304 }
1305 }
1306 if let Some(current) = n {
1307 current.is_deleted()
1308 } else {
1309 false
1310 }
1311 } {}
1312 }
1313 self.first_call = false;
1314 self.current = n;
1315 }
1316 if let Some(current) = self.current {
1317 if let ItemContent::Type(t) = ¤t.content {
1318 result = XmlOut::try_from(BranchPtr::from(t)).ok();
1319 }
1320 }
1321 result
1322 }
1323}
1324
1325pub struct XmlTextEvent {
1327 pub(crate) current_target: BranchPtr,
1328 target: XmlTextRef,
1329 delta: UnsafeCell<Option<Vec<Delta>>>,
1330 keys: UnsafeCell<Result<HashMap<Arc<str>, EntryChange>, HashSet<Option<Arc<str>>>>>,
1331}
1332
1333impl XmlTextEvent {
1334 pub(crate) fn new(branch_ref: BranchPtr, key_changes: HashSet<Option<Arc<str>>>) -> Self {
1335 let current_target = branch_ref.clone();
1336 let target = XmlTextRef::from(branch_ref);
1337 XmlTextEvent {
1338 target,
1339 current_target,
1340 delta: UnsafeCell::new(None),
1341 keys: UnsafeCell::new(Err(key_changes)),
1342 }
1343 }
1344
1345 pub fn target(&self) -> &XmlTextRef {
1347 &self.target
1348 }
1349
1350 pub fn path(&self) -> Path {
1352 Branch::path(self.current_target, self.target.0)
1353 }
1354
1355 pub fn delta(&self, txn: &TransactionMut) -> &[Delta] {
1358 let delta = unsafe { self.delta.get().as_mut().unwrap() };
1359 delta
1360 .get_or_insert_with(|| TextEvent::get_delta(self.target.0, txn))
1361 .as_slice()
1362 }
1363
1364 pub fn keys(&self, txn: &TransactionMut) -> &HashMap<Arc<str>, EntryChange> {
1367 let keys = unsafe { self.keys.get().as_mut().unwrap() };
1368
1369 match keys {
1370 Ok(keys) => {
1371 return keys;
1372 }
1373 Err(subs) => {
1374 let subs = event_keys(txn, self.target.0, subs);
1375 *keys = Ok(subs);
1376 if let Ok(keys) = keys {
1377 keys
1378 } else {
1379 panic!("Defect: should not happen");
1380 }
1381 }
1382 }
1383 }
1384}
1385
1386pub struct Siblings<'a, T> {
1387 current: Option<ItemPtr>,
1388 _txn: &'a T,
1389}
1390
1391impl<'a, T> Siblings<'a, T> {
1392 fn new(current: Option<ItemPtr>, txn: &'a T) -> Self {
1393 Siblings { current, _txn: txn }
1394 }
1395}
1396
1397impl<'a, T> Iterator for Siblings<'a, T> {
1398 type Item = XmlOut;
1399
1400 fn next(&mut self) -> Option<Self::Item> {
1401 while let Some(item) = self.current.as_deref() {
1402 self.current = item.right;
1403 if let Some(right) = self.current.as_deref() {
1404 if !right.is_deleted() {
1405 if let ItemContent::Type(inner) = &right.content {
1406 let ptr = BranchPtr::from(inner);
1407 return XmlOut::try_from(ptr).ok();
1408 }
1409 }
1410 }
1411 }
1412
1413 None
1414 }
1415}
1416
1417impl<'a, T> DoubleEndedIterator for Siblings<'a, T> {
1418 fn next_back(&mut self) -> Option<Self::Item> {
1419 while let Some(item) = self.current.as_deref() {
1420 self.current = item.left;
1421 if let Some(left) = self.current.as_deref() {
1422 if !left.is_deleted() {
1423 if let ItemContent::Type(inner) = &left.content {
1424 let ptr = BranchPtr::from(inner);
1425 return XmlOut::try_from(ptr).ok();
1426 }
1427 }
1428 }
1429 }
1430
1431 None
1432 }
1433}
1434
1435pub struct XmlEvent {
1437 pub(crate) current_target: BranchPtr,
1438 target: XmlOut,
1439 change_set: UnsafeCell<Option<Box<ChangeSet<Change>>>>,
1440 keys: UnsafeCell<Result<HashMap<Arc<str>, EntryChange>, HashSet<Option<Arc<str>>>>>,
1441 children_changed: bool,
1442}
1443
1444impl XmlEvent {
1445 pub(crate) fn new(branch_ref: BranchPtr, key_changes: HashSet<Option<Arc<str>>>) -> Self {
1446 let current_target = branch_ref.clone();
1447 let children_changed = key_changes.iter().any(Option::is_none);
1448 XmlEvent {
1449 target: XmlOut::try_from(branch_ref).unwrap(),
1450 current_target,
1451 change_set: UnsafeCell::new(None),
1452 keys: UnsafeCell::new(Err(key_changes)),
1453 children_changed,
1454 }
1455 }
1456
1457 pub fn children_changed(&self) -> bool {
1459 self.children_changed
1460 }
1461
1462 pub fn target(&self) -> &XmlOut {
1464 &self.target
1465 }
1466
1467 pub fn path(&self) -> Path {
1469 Branch::path(self.current_target, self.target.as_ptr())
1470 }
1471
1472 pub fn delta(&self, txn: &TransactionMut) -> &[Change] {
1475 self.changes(txn).delta.as_slice()
1476 }
1477
1478 pub fn added(&self, txn: &TransactionMut) -> &HashSet<ID> {
1481 &self.changes(txn).added
1482 }
1483
1484 pub fn deleted(&self, txn: &TransactionMut) -> &HashSet<ID> {
1487 &self.changes(txn).deleted
1488 }
1489
1490 pub fn keys(&self, txn: &TransactionMut) -> &HashMap<Arc<str>, EntryChange> {
1493 let keys = unsafe { self.keys.get().as_mut().unwrap() };
1494
1495 match keys {
1496 Ok(keys) => keys,
1497 Err(subs) => {
1498 let subs = event_keys(txn, self.target.as_ptr(), subs);
1499 *keys = Ok(subs);
1500 if let Ok(keys) = keys {
1501 keys
1502 } else {
1503 panic!("Defect: should not happen");
1504 }
1505 }
1506 }
1507 }
1508
1509 fn changes(&self, txn: &TransactionMut) -> &ChangeSet<Change> {
1510 let change_set = unsafe { self.change_set.get().as_mut().unwrap() };
1511 change_set
1512 .get_or_insert_with(|| Box::new(event_change_set(txn, self.target.as_ptr().start)))
1513 }
1514}
1515
1516#[cfg(test)]
1517mod test {
1518 use std::collections::{HashMap, HashSet};
1519 use std::sync::Arc;
1520
1521 use arc_swap::ArcSwapOption;
1522
1523 use crate::test_utils::exchange_updates;
1524 use crate::transaction::ReadTxn;
1525 use crate::types::xml::{Xml, XmlFragment, XmlOut};
1526 use crate::types::{Attrs, Change, EntryChange, Out};
1527 use crate::updates::decoder::Decode;
1528 use crate::updates::encoder::{Encoder, EncoderV1};
1529 use crate::{
1530 Any, Doc, GetString, Observable, SharedRef, StateVector, Text, Transact, Update,
1531 XmlElementPrelim, XmlTextPrelim, XmlTextRef,
1532 };
1533
1534 #[test]
1535 fn insert_attribute() {
1536 let d1 = Doc::with_client_id(1);
1537 let f = d1.get_or_insert_xml_fragment("xml");
1538 let mut t1 = d1.transact_mut();
1539 let xml1 = f.push_back(&mut t1, XmlElementPrelim::empty("div"));
1540 xml1.insert_attribute(&mut t1, "height", 10.to_string());
1541 assert_eq!(xml1.get_attribute(&t1, "height"), Some(Out::from("10")));
1542
1543 let d2 = Doc::with_client_id(1);
1544 let f = d2.get_or_insert_xml_fragment("xml");
1545 let mut t2 = d2.transact_mut();
1546 let xml2 = f.push_back(&mut t2, XmlElementPrelim::empty("div"));
1547 let u = t1.encode_state_as_update_v1(&StateVector::default());
1548 let u = Update::decode_v1(u.as_slice()).unwrap();
1549 t2.apply_update(u).unwrap();
1550 assert_eq!(xml2.get_attribute(&t2, "height"), Some(Out::from("10")));
1551 }
1552
1553 #[test]
1554 fn tree_walker() {
1555 let doc = Doc::with_client_id(1);
1556 let root = doc.get_or_insert_xml_fragment("xml");
1557 let mut txn = doc.transact_mut();
1558 let p1 = root.push_back(&mut txn, XmlElementPrelim::empty("p"));
1566 p1.push_back(&mut txn, XmlTextPrelim::new(""));
1567 p1.push_back(&mut txn, XmlTextPrelim::new(""));
1568 let p2 = root.push_back(&mut txn, XmlElementPrelim::empty("p"));
1569 root.push_back(&mut txn, XmlElementPrelim::empty("img"));
1570
1571 let all_paragraphs = root.successors(&txn).filter_map(|n| match n {
1572 XmlOut::Element(e) if e.tag() == &"p".into() => Some(e),
1573 _ => None,
1574 });
1575 let actual: Vec<_> = all_paragraphs.collect();
1576
1577 assert_eq!(
1578 actual.len(),
1579 2,
1580 "query selector should found two paragraphs"
1581 );
1582 assert_eq!(
1583 actual[0].hook(),
1584 p1.hook(),
1585 "query selector found 1st paragraph"
1586 );
1587 assert_eq!(
1588 actual[1].hook(),
1589 p2.hook(),
1590 "query selector found 2nd paragraph"
1591 );
1592 }
1593
1594 #[test]
1595 fn text_attributes() {
1596 let doc = Doc::with_client_id(1);
1597 let f = doc.get_or_insert_xml_fragment("test");
1598 let mut txn = doc.transact_mut();
1599 let txt = f.push_back(&mut txn, XmlTextPrelim::new(""));
1600 txt.insert_attribute(&mut txn, "test", 42.to_string());
1601
1602 assert_eq!(txt.get_attribute(&txn, "test"), Some(Out::from("42")));
1603 let actual: Vec<_> = txt.attributes(&txn).collect();
1604 let expected: Vec<_> = vec![("test", Out::from("42"))].into_iter().collect();
1605 assert_eq!(actual, expected);
1606 }
1607
1608 #[test]
1609 fn text_attributes_any() {
1610 let doc = Doc::with_client_id(1);
1611 let f = doc.get_or_insert_xml_fragment("test");
1612 let mut txn = doc.transact_mut();
1613 let txt = f.push_back(&mut txn, XmlTextPrelim::new(""));
1614 txt.insert_attribute(&mut txn, "test", Any::BigInt(42));
1615 txt.insert_attribute(&mut txn, "test_true", true);
1616 txt.insert_attribute(&mut txn, "test_null", Any::Null);
1617
1618 assert_eq!(
1619 txt.get_attribute(&txn, "test"),
1620 Some(Out::Any(Any::BigInt(42)))
1621 );
1622 assert_eq!(
1623 txt.get_attribute(&txn, "test_true"),
1624 Some(Out::Any(Any::Bool(true)))
1625 );
1626 assert_eq!(
1627 txt.get_attribute(&txn, "test_null"),
1628 Some(Out::Any(Any::Null))
1629 );
1630
1631 let actual_keys: HashSet<&str> = txt.attributes(&txn).map(|(k, _)| k).collect();
1633 let expected_keys: HashSet<&str> =
1634 vec!["test", "test_true", "test_null"].into_iter().collect();
1635 assert_eq!(actual_keys, expected_keys);
1636 }
1637
1638 #[test]
1639 fn siblings() {
1640 let doc = Doc::with_client_id(1);
1641 let root = doc.get_or_insert_xml_fragment("root");
1642 let mut txn = doc.transact_mut();
1643 let first = root.push_back(&mut txn, XmlTextPrelim::new("hello"));
1644 let second = root.push_back(&mut txn, XmlElementPrelim::empty("p"));
1645
1646 assert_eq!(
1647 &first.siblings(&txn).next().unwrap().id(),
1648 second.hook().id(),
1649 "first.next_sibling should point to second"
1650 );
1651 assert_eq!(
1652 &second.siblings(&txn).next_back().unwrap().id(),
1653 first.hook().id(),
1654 "second.prev_sibling should point to first"
1655 );
1656 assert_eq!(
1657 &first.parent().unwrap().id(),
1658 root.hook().id(),
1659 "first.parent should point to root"
1660 );
1661 assert!(root.parent().is_none(), "root parent should not exist");
1662 assert_eq!(
1663 &root.first_child().unwrap().id(),
1664 first.hook().id(),
1665 "root.first_child should point to first"
1666 );
1667 }
1668
1669 #[test]
1670 fn serialization() {
1671 let d1 = Doc::with_client_id(1);
1672 let r1 = d1.get_or_insert_xml_fragment("root");
1673 let mut t1 = d1.transact_mut();
1674 let _first = r1.push_back(&mut t1, XmlTextPrelim::new("hello"));
1675 r1.push_back(&mut t1, XmlElementPrelim::empty("p"));
1676
1677 let expected = "hello<p></p>";
1678 assert_eq!(r1.get_string(&t1), expected);
1679
1680 let u1 = t1.encode_state_as_update_v1(&StateVector::default());
1681
1682 let d2 = Doc::with_client_id(2);
1683 let r2 = d2.get_or_insert_xml_fragment("root");
1684 let mut t2 = d2.transact_mut();
1685
1686 let u1 = Update::decode_v1(u1.as_slice()).unwrap();
1687 t2.apply_update(u1).unwrap();
1688 assert_eq!(r2.get_string(&t2), expected);
1689 }
1690
1691 #[test]
1692 fn serialization_compatibility() {
1693 let d1 = Doc::with_client_id(1);
1694 let r1 = d1.get_or_insert_xml_fragment("root");
1695 let mut t1 = d1.transact_mut();
1696 let _first = r1.push_back(&mut t1, XmlTextPrelim::new("hello"));
1697 r1.push_back(&mut t1, XmlElementPrelim::empty("p"));
1698
1699 let expected = &[
1712 1, 3, 1, 0, 7, 1, 4, 114, 111, 111, 116, 6, 4, 0, 1, 0, 5, 104, 101, 108, 108, 111,
1713 135, 1, 0, 3, 1, 112, 0,
1714 ];
1715 let u1 = t1.encode_state_as_update_v1(&StateVector::default());
1716 assert_eq!(u1.as_slice(), expected);
1717 }
1718
1719 #[test]
1720 fn event_observers() {
1721 let d1 = Doc::with_client_id(1);
1722 let f = d1.get_or_insert_xml_fragment("xml");
1723 let xml = f.insert(&mut d1.transact_mut(), 0, XmlElementPrelim::empty("test"));
1724
1725 let d2 = Doc::with_client_id(2);
1726 let f = d2.get_or_insert_xml_fragment("xml");
1727 exchange_updates(&[&d1, &d2]);
1728 let xml2 = f
1729 .get(&d2.transact(), 0)
1730 .unwrap()
1731 .into_xml_element()
1732 .unwrap();
1733
1734 let attributes = Arc::new(ArcSwapOption::default());
1735 let nodes = Arc::new(ArcSwapOption::default());
1736 let attributes_c = attributes.clone();
1737 let nodes_c = nodes.clone();
1738 let _sub = xml.observe(move |txn, e| {
1739 attributes_c.store(Some(Arc::new(e.keys(txn).clone())));
1740 nodes_c.store(Some(Arc::new(e.delta(txn).to_vec())));
1741 });
1742
1743 {
1745 let mut txn = d1.transact_mut();
1746 xml.insert_attribute(&mut txn, "key1", "value1");
1747 xml.insert_attribute(&mut txn, "key2", "value2");
1748 }
1749 assert!(nodes.swap(None).unwrap().is_empty());
1750 assert_eq!(
1751 attributes.swap(None),
1752 Some(Arc::new(HashMap::from([
1753 (
1754 "key1".into(),
1755 EntryChange::Inserted(Any::String("value1".into()).into())
1756 ),
1757 (
1758 "key2".into(),
1759 EntryChange::Inserted(Any::String("value2".into()).into())
1760 )
1761 ])))
1762 );
1763
1764 {
1766 let mut txn = d1.transact_mut();
1767 xml.insert_attribute(&mut txn, "key1", "value11");
1768 xml.remove_attribute(&mut txn, &"key2");
1769 }
1770 assert!(nodes.swap(None).unwrap().is_empty());
1771 assert_eq!(
1772 attributes.swap(None),
1773 Some(Arc::new(HashMap::from([
1774 (
1775 "key1".into(),
1776 EntryChange::Updated(
1777 Any::String("value1".into()).into(),
1778 Any::String("value11".into()).into()
1779 )
1780 ),
1781 (
1782 "key2".into(),
1783 EntryChange::Removed(Any::String("value2".into()).into())
1784 )
1785 ])))
1786 );
1787
1788 let (nested_txt, nested_xml) = {
1790 let mut txn = d1.transact_mut();
1791 let txt = xml.insert(&mut txn, 0, XmlTextPrelim::new(""));
1792 let xml2 = xml.insert(&mut txn, 1, XmlElementPrelim::empty("div"));
1793 (txt, xml2)
1794 };
1795 assert_eq!(
1796 nodes.swap(None),
1797 Some(Arc::new(vec![Change::Added(vec![
1798 Out::YXmlText(nested_txt.clone()),
1799 Out::YXmlElement(nested_xml.clone())
1800 ])]))
1801 );
1802 assert_eq!(attributes.swap(None), Some(HashMap::new().into()));
1803
1804 let nested_xml2 = {
1806 let mut txn = d1.transact_mut();
1807 xml.remove_range(&mut txn, 1, 1);
1808 xml.insert(&mut txn, 1, XmlElementPrelim::empty("p"))
1809 };
1810 assert_eq!(
1811 nodes.swap(None),
1812 Some(Arc::new(vec![
1813 Change::Retain(1),
1814 Change::Added(vec![Out::YXmlElement(nested_xml2.clone())]),
1815 Change::Removed(1),
1816 ]))
1817 );
1818 assert_eq!(attributes.swap(None), Some(HashMap::new().into()));
1819
1820 let attributes = Arc::new(ArcSwapOption::default());
1822 let nodes = Arc::new(ArcSwapOption::default());
1823 let attributes_c = attributes.clone();
1824 let nodes_c = nodes.clone();
1825 let _sub = xml2.observe(move |txn, e| {
1826 attributes_c.store(Some(Arc::new(e.keys(txn).clone())));
1827 nodes_c.store(Some(Arc::new(e.delta(txn).to_vec())));
1828 });
1829
1830 {
1831 let t1 = d1.transact_mut();
1832 let mut t2 = d2.transact_mut();
1833 let sv = t2.state_vector();
1834 let mut encoder = EncoderV1::new();
1835 t1.encode_diff(&sv, &mut encoder);
1836 let update = Update::decode_v1(encoder.to_vec().as_slice()).unwrap();
1837 t2.apply_update(update).unwrap();
1838 }
1839 assert_eq!(
1840 nodes.swap(None),
1841 Some(Arc::new(vec![Change::Added(vec![
1842 Out::YXmlText(nested_txt),
1843 Out::YXmlElement(nested_xml2)
1844 ])]))
1845 );
1846 assert_eq!(
1847 attributes.swap(None),
1848 Some(Arc::new(HashMap::from([(
1849 "key1".into(),
1850 EntryChange::Inserted(Any::String("value11".into()).into())
1851 )])))
1852 );
1853 }
1854
1855 #[test]
1856 fn xml_to_string() {
1857 let doc = Doc::new();
1858 let f = doc.get_or_insert_xml_fragment("test");
1859 let mut txn = doc.transact_mut();
1860 let div = f.push_back(&mut txn, XmlElementPrelim::empty("div"));
1861 div.insert_attribute(&mut txn, "class", "t-button");
1862 let text = div.push_back(&mut txn, XmlTextPrelim::new("hello world"));
1863 text.format(
1864 &mut txn,
1865 6,
1866 5,
1867 Attrs::from([(
1868 "a".into(),
1869 HashMap::from([("href".into(), "http://domain.org")]).into(),
1870 )]),
1871 );
1872 drop(txn);
1873
1874 let str = f.get_string(&doc.transact());
1875 assert_eq!(
1876 str.as_str(),
1877 "<div class=\"t-button\">hello <a href=\"http://domain.org\">world</a></div>"
1878 )
1879 }
1880
1881 #[test]
1882 fn xml_to_string_2() {
1883 let doc = Doc::new();
1884 let f = doc.get_or_insert_xml_fragment("article");
1885 let xml = f.insert(&mut doc.transact_mut(), 0, XmlTextPrelim::new(""));
1886 let mut txn = doc.transact_mut();
1887
1888 let bold = Attrs::from([("b".into(), true.into())]);
1889 let italic = Attrs::from([("i".into(), true.into())]);
1890
1891 xml.insert(&mut txn, 0, "hello ");
1892 xml.insert_with_attributes(&mut txn, 6, "world", italic);
1893 xml.format(&mut txn, 0, 5, bold);
1894
1895 assert_eq!(xml.get_string(&txn), "<b>hello</b> <i>world</i>");
1896
1897 let remove_italic = Attrs::from([("i".into(), Any::Null)]);
1898 xml.format(&mut txn, 6, 5, remove_italic);
1899
1900 assert_eq!(xml.get_string(&txn), "<b>hello</b> world");
1901 }
1902
1903 #[test]
1904 fn format_attributes_decode_compatibility_v1() {
1905 let data = &[
1906 1, 6, 1, 0, 6, 1, 4, 116, 101, 115, 116, 1, 105, 4, 116, 114, 117, 101, 132, 1, 0, 6,
1907 104, 101, 108, 108, 111, 32, 132, 1, 6, 5, 119, 111, 114, 108, 100, 134, 1, 11, 1, 105,
1908 4, 110, 117, 108, 108, 198, 1, 6, 1, 7, 1, 98, 4, 116, 114, 117, 101, 134, 1, 12, 1,
1909 98, 4, 110, 117, 108, 108, 0,
1910 ];
1911 let update = Update::decode_v1(data).unwrap();
1912 let doc = Doc::new();
1913 let txt = doc.get_or_insert_text("test");
1914 let txt: &XmlTextRef = txt.as_ref();
1915 let mut txn = doc.transact_mut();
1916
1917 txn.apply_update(update).unwrap();
1918 assert_eq!(txt.get_string(&txn), "<i>hello </i><b><i>world</i></b>");
1919
1920 let actual = txn.encode_state_as_update_v1(&StateVector::default());
1921 assert_eq!(actual, data);
1922 }
1923
1924 #[test]
1925 fn format_attributes_decode_compatibility_v2() {
1926 let data = &[
1927 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,
1928 134, 26, 19, 116, 101, 115, 116, 105, 104, 101, 108, 108, 111, 32, 119, 111, 114, 108,
1929 100, 105, 98, 98, 4, 1, 6, 5, 65, 1, 1, 1, 0, 0, 1, 6, 0, 120, 126, 120, 126, 0,
1930 ];
1931 let update = Update::decode_v2(data).unwrap();
1932 let doc = Doc::new();
1933 let txt = doc.get_or_insert_text("test");
1934 let txt: &XmlTextRef = txt.as_ref();
1935 let mut txn = doc.transact_mut();
1936
1937 txn.apply_update(update).unwrap();
1938 assert_eq!(txt.get_string(&txn), "<i>hello </i><b><i>world</i></b>");
1939
1940 let actual = txn.encode_state_as_update_v2(&StateVector::default());
1941 assert_eq!(actual, data);
1942 }
1943}