1use alloc::boxed::Box;
5use alloc::collections::btree_map::Entry;
6use alloc::collections::BTreeMap;
7use alloc::collections::BTreeSet;
8use alloc::format;
9use alloc::vec::Vec;
10
11use bytes::{BufMut, BytesMut};
12
13use crate::error::{Error, ErrorContext, Result};
14use crate::parser::{Event, XmlVersion, XMLNS_XML, XMLNS_XMLNS};
15use crate::strings::{Name, Namespace, NcName, NcNameStr};
16
17const XML_DECL: &[u8] = b"<?xml version='1.0' encoding='utf-8'?>\n";
18
19pub const PREFIX_XML: &NcNameStr = unsafe { core::mem::transmute("xml") };
21
22pub const PREFIX_XMLNS: &NcNameStr = unsafe { core::mem::transmute("xmlns") };
24
25fn escape_text<'a, B: BufMut>(
26 out: &'a mut B,
27 data: &'a str,
28 attribute_context: bool,
29) -> core::result::Result<(), rxml_validation::Error> {
30 let data = data.as_bytes();
31 let mut last_index = 0;
32 for i in 0..data.len() {
33 let ch = data[i];
34 let escaped: &[u8] = match ch {
35 b'\x00'..=b'\x08' | b'\x0b' | b'\x0c' | b'\x0e'..=b'\x1f' => {
36 return Err(rxml_validation::Error::InvalidChar(ch.into()));
37 }
38 b'"' if attribute_context => &b"""[..],
39 b'\'' if attribute_context => &b"'"[..],
40 b'<' => &b"<"[..],
41 b'>' => &b">"[..],
42 b'&' => &b"&"[..],
43 b'\r' => &b"
"[..],
44 b'\n' if attribute_context => &b"
"[..],
45 b'\t' if attribute_context => &b"	"[..],
46 b'\xbe' | b'\xbf' => {
47 if i >= 2 && data[i - 2] == b'\xef' && data[i - 1] == b'\xbf' {
48 let low_bit = ch & 0x01;
50 return Err(rxml_validation::Error::InvalidChar(unsafe {
54 char::from_u32_unchecked(0xfffe | low_bit as u32)
55 }));
56 } else {
57 continue;
58 }
59 }
60 _ => continue,
61 };
62 if i > last_index {
63 out.put_slice(&data[last_index..i]);
64 }
65 out.put_slice(escaped);
66 last_index = i + 1;
67 }
68 out.put_slice(&data[last_index..data.len()]);
69 Ok(())
70}
71
72#[derive(Debug)]
80pub enum Item<'x> {
81 XmlDeclaration(XmlVersion),
83
84 ElementHeadStart(
86 Namespace<'x>,
88 &'x NcNameStr,
90 ),
91
92 Attribute(
94 Namespace<'x>,
96 &'x NcNameStr,
98 &'x str,
100 ),
101
102 ElementHeadEnd,
104
105 Text(&'x str),
107
108 ElementFoot,
118}
119
120impl Item<'_> {
121 fn name(&self) -> &'static str {
122 match self {
123 Self::XmlDeclaration { .. } => "xml declaration",
124 Self::ElementHeadStart { .. } => "element start",
125 Self::Attribute { .. } => "attribute",
126 Self::ElementHeadEnd => "element head end",
127 Self::Text { .. } => "text",
128 Self::ElementFoot => "element foot",
129 }
130 }
131}
132
133#[derive(Debug)]
135pub enum PrefixError {
136 Undeclared,
138}
139
140pub trait TrackNamespace {
154 fn declare_fixed(&mut self, prefix: Option<&NcNameStr>, name: Namespace<'static>) -> bool;
167
168 fn declare_auto(&mut self, name: Namespace<'static>) -> (bool, Option<&NcNameStr>);
181
182 fn declare_with_auto_prefix(&mut self, name: Namespace<'static>) -> (bool, &NcNameStr);
196
197 fn get_prefix_or_default(
200 &self,
201 name: Namespace<'static>,
202 ) -> core::result::Result<Option<&NcNameStr>, PrefixError>;
203
204 fn get_prefix(&self, name: Namespace<'static>)
209 -> core::result::Result<&NcNameStr, PrefixError>;
210
211 fn push(&mut self);
213
214 fn pop(&mut self);
216
217 fn new_default_declaration(&self) -> Option<&Namespace<'static>>;
226
227 fn new_prefix_declarations(
229 &self,
230 ) -> Box<dyn Iterator<Item = (&Namespace<'static>, &NcNameStr)> + '_>;
231}
232
233#[derive(Debug, Default)]
247pub struct SimpleNamespaces {
248 global_ns: BTreeMap<Namespace<'static>, NcName>,
250 global_ns_rev: BTreeSet<NcName>,
251 global_ns_ctr: usize,
252 default_ns_stack: Vec<Namespace<'static>>,
253
254 next_default_ns: Option<Namespace<'static>>,
256 temp_ns_ctr: usize,
257 temp_ns: BTreeMap<Namespace<'static>, NcName>,
258 temp_ns_rev: BTreeSet<NcName>,
259}
260
261impl SimpleNamespaces {
262 pub fn new() -> Self {
264 Self::default()
265 }
266
267 pub fn lookup_prefix(
276 &self,
277 prefix: Option<&NcNameStr>,
278 ) -> core::result::Result<Namespace<'static>, PrefixError> {
279 match prefix {
280 Some(prefix) if prefix == PREFIX_XML => Ok(Namespace::XML),
281 Some(prefix) if prefix == PREFIX_XMLNS => Ok(Namespace::XMLNS),
282 Some(prefix) => {
283 for (decl_uri, decl_prefix) in self.temp_ns.iter().chain(self.global_ns.iter()) {
284 if decl_prefix == prefix {
285 return Ok(decl_uri.clone());
286 }
287 }
288 Err(PrefixError::Undeclared)
289 }
290 None => {
291 if let Some(uri) = self.next_default_ns.as_ref() {
292 return Ok(uri.clone());
293 }
294 match self.default_ns_stack.last() {
295 Some(uri) => Ok(uri.clone()),
296 _ => Err(PrefixError::Undeclared),
297 }
298 }
299 }
300 }
301}
302
303impl TrackNamespace for SimpleNamespaces {
304 fn declare_fixed(&mut self, prefix: Option<&NcNameStr>, name: Namespace<'static>) -> bool {
305 match prefix.as_ref() {
306 Some(v) if *v == PREFIX_XML => {
307 if name == XMLNS_XML {
308 return false;
309 }
310 panic!("xml is a reserved prefix")
311 }
312 Some(v) if *v == PREFIX_XMLNS => {
313 if name == XMLNS_XMLNS {
314 return false;
315 }
316 panic!("xmlns is a reserved prefix")
317 }
318 _ => {}
319 }
320
321 if name == XMLNS_XML {
322 panic!("{} must be bound to xml prefix", name)
323 }
324 if name == XMLNS_XMLNS {
325 panic!("{} must be bound to xmlns prefix", name)
326 }
327
328 match prefix {
329 Some(prefix) => {
330 if self.global_ns_rev.contains(prefix) {
331 panic!(
332 "prefix declaration conflicts with global prefix: {:?}",
333 prefix
334 )
335 }
336 if self.temp_ns_rev.contains(prefix) {
337 panic!("duplicate prefix: {:?}", prefix);
338 }
339 self.temp_ns.insert(name, prefix.to_ncname());
340 self.temp_ns_rev.insert(prefix.to_ncname());
341 true
342 }
343 None => {
344 if self.next_default_ns.is_some() {
345 panic!("duplicate default namespace")
346 }
347 self.next_default_ns = Some(name);
348 true
349 }
350 }
351 }
352
353 fn declare_auto(&mut self, name: Namespace<'static>) -> (bool, Option<&NcNameStr>) {
354 if name == XMLNS_XML {
355 return (false, Some(PREFIX_XML));
356 }
357 if name == XMLNS_XMLNS {
358 return (false, Some(PREFIX_XMLNS));
359 }
360
361 match self
365 .next_default_ns
366 .as_ref()
367 .or(self.default_ns_stack.last())
368 {
369 Some(default_name) if *default_name == name => return (false, None),
371 _ => (),
373 };
374
375 match self.temp_ns.entry(name) {
377 Entry::Occupied(o) => (false, Some(o.into_mut())),
379 Entry::Vacant(v_temp) => match self.global_ns.entry(v_temp.key().clone()) {
381 Entry::Occupied(o) => (false, Some(o.into_mut())),
383 Entry::Vacant(_) => {
385 match self.next_default_ns.as_ref() {
387 Some(_) => {
389 let ctr = self.temp_ns_ctr;
390 let temp_ns_prefix: NcName = format!("tns{}", ctr)
391 .try_into()
392 .expect("auto-generated prefix must always be valid");
393 if self.global_ns_rev.contains(&temp_ns_prefix) {
394 panic!(
395 "automatic prefix declaration conflicts with global prefix: {:?}",
396 temp_ns_prefix
397 )
398 }
399 if self.temp_ns_rev.contains(&temp_ns_prefix) {
400 panic!(
401 "automatic prefix declaration conflicts with local prefix: {:?}",
402 temp_ns_prefix
403 )
404 }
405 self.temp_ns_ctr += 1;
406 self.temp_ns_rev.insert(temp_ns_prefix.clone());
407 (true, Some(v_temp.insert(temp_ns_prefix)))
408 }
409 None => {
411 let name = v_temp.into_key();
412 let new = match self.default_ns_stack.last() {
413 Some(v) if v == &name => {
414 self.next_default_ns = Some(v.clone());
416 false
418 }
419 _ => {
420 let new = !name.is_none();
424 self.next_default_ns = Some(name);
426 new
427 }
428 };
429 (new, None)
430 }
431 }
432 }
433 },
434 }
435 }
436
437 fn declare_with_auto_prefix(&mut self, name: Namespace<'static>) -> (bool, &NcNameStr) {
438 if name == XMLNS_XML {
439 return (false, PREFIX_XML);
440 }
441 if name == XMLNS_XMLNS {
442 return (false, PREFIX_XMLNS);
443 }
444
445 match self.temp_ns.entry(name.clone()) {
446 Entry::Occupied(o) => (false, o.into_mut()),
447 Entry::Vacant(v) => match self.global_ns.entry(name.clone()) {
448 Entry::Occupied(o) => (false, o.into_mut()),
449 Entry::Vacant(_) => {
450 let ctr = self.temp_ns_ctr;
451 let temp_ns_prefix: NcName = format!("tns{}", ctr)
452 .try_into()
453 .expect("auto-generated prefix must always be valid");
454 if self.global_ns_rev.contains(&temp_ns_prefix) {
455 panic!(
456 "automatic prefix declaration conflicts with global prefix: {:?}",
457 temp_ns_prefix
458 )
459 }
460 if self.temp_ns_rev.contains(&temp_ns_prefix) {
461 panic!(
462 "automatic prefix declaration conflicts with local prefix: {:?}",
463 temp_ns_prefix
464 )
465 }
466 self.temp_ns_ctr += 1;
467 self.temp_ns_rev.insert(temp_ns_prefix.clone());
468 (true, v.insert(temp_ns_prefix))
469 }
470 },
471 }
472 }
473
474 fn get_prefix_or_default(
475 &self,
476 name: Namespace<'static>,
477 ) -> core::result::Result<Option<&NcNameStr>, PrefixError> {
478 match self
479 .next_default_ns
480 .as_ref()
481 .or(self.default_ns_stack.last())
482 {
483 Some(default_name) if *default_name == name => Ok(None),
484 _ => Ok(Some(self.get_prefix(name)?)),
485 }
486 }
487
488 fn get_prefix(
489 &self,
490 name: Namespace<'static>,
491 ) -> core::result::Result<&NcNameStr, PrefixError> {
492 self.temp_ns
493 .get(&name)
494 .or(self.global_ns.get(&name))
495 .map(|x| &**x)
496 .ok_or(PrefixError::Undeclared)
497 }
498
499 fn push(&mut self) {
500 match self.next_default_ns.take() {
501 None => {
502 let old = self
505 .default_ns_stack
506 .last()
507 .unwrap_or(Namespace::none())
508 .clone();
509 self.default_ns_stack.push(old);
510 }
511 Some(v) => self.default_ns_stack.push(v),
512 }
513 if self.default_ns_stack.len() == 1 {
514 core::mem::swap(&mut self.global_ns, &mut self.temp_ns);
516 core::mem::swap(&mut self.global_ns_rev, &mut self.temp_ns_rev);
517 self.global_ns_ctr = self.temp_ns_ctr;
518 }
519
520 self.temp_ns_ctr = self.global_ns_ctr;
521 self.temp_ns.clear();
522 self.temp_ns_rev.clear();
523 }
524
525 fn pop(&mut self) {
526 self.default_ns_stack.pop();
527 }
528
529 fn new_default_declaration(&self) -> Option<&Namespace<'static>> {
530 match self.next_default_ns.as_ref() {
531 Some(ns) if ns.is_none() && self.default_ns_stack.is_empty() => None,
533 other => other,
534 }
535 }
536
537 fn new_prefix_declarations(
538 &self,
539 ) -> Box<dyn Iterator<Item = (&Namespace<'static>, &NcNameStr)> + '_> {
540 Box::new(self.temp_ns.iter().map(|(k, v)| (k, &**v)))
541 }
542}
543
544#[derive(Debug, Clone, Copy, Default, PartialEq, Eq)]
545enum EncoderState {
546 #[default]
547 Start,
548 Declared,
549 ElementHead,
550 Content,
551 EndOfDocument,
552}
553
554impl EncoderState {
555 fn ctx(&self) -> Option<ErrorContext> {
556 Some(match self {
557 Self::Start => ErrorContext::XmlDeclarationStart,
558 Self::Declared => ErrorContext::DocumentBegin,
559 Self::ElementHead => ErrorContext::Element,
560 Self::Content => ErrorContext::Text,
561 Self::EndOfDocument => ErrorContext::DocumentEnd,
562 })
563 }
564}
565
566#[derive(Default)]
582pub struct Encoder<T> {
583 state: EncoderState,
584 qname_stack: Vec<Name>,
585 ns: T,
586}
587
588impl Encoder<SimpleNamespaces> {
589 pub fn new() -> Self {
595 Self::default()
596 }
597}
598
599impl<T: TrackNamespace> From<T> for Encoder<T> {
600 fn from(ns: T) -> Self {
604 Self {
605 state: EncoderState::Start,
606 qname_stack: Vec::new(),
607 ns,
608 }
609 }
610}
611
612impl<T: TrackNamespace> Encoder<T> {
613 fn encode_nsdecl<O: BufMut>(
614 prefix: Option<&NcNameStr>,
615 nsuri: &str,
616 output: &mut O,
617 ) -> core::result::Result<(), rxml_validation::Error> {
618 match prefix {
619 Some(prefix) => {
620 output.put_slice(b" xmlns:");
621 output.put_slice(prefix.as_bytes());
622 output.put_slice(b"='");
623 }
624 None => {
625 output.put_slice(b" xmlns='");
626 }
627 }
628 escape_text(output, nsuri, true)?;
629 output.put_u8(b'\'');
630 Ok(())
631 }
632
633 pub fn ns_tracker(&self) -> &T {
635 &self.ns
636 }
637
638 pub fn ns_tracker_mut(&mut self) -> &mut T {
640 &mut self.ns
641 }
642
643 pub fn encode<O: BufMut>(&mut self, item: Item<'_>, output: &mut O) -> Result<()> {
650 if self.state == EncoderState::EndOfDocument {
651 return Err(Error::UnexpectedToken(self.state.ctx(), item.name(), None));
652 }
653
654 match item {
655 Item::XmlDeclaration(XmlVersion::V1_0) => match self.state {
656 EncoderState::Start => {
657 output.put_slice(XML_DECL);
658 self.state = EncoderState::Declared;
659 Ok(())
660 }
661 _ => Err(Error::UnexpectedToken(self.state.ctx(), item.name(), None)),
662 },
663 Item::ElementHeadStart(ref nsuri, local_name) => match self.state {
664 EncoderState::Start | EncoderState::Declared | EncoderState::Content => {
665 output.put_u8(b'<');
666 let (_, prefix) = self.ns.declare_auto(nsuri.clone().into_static());
667 let qname = match prefix {
668 Some(prefix) => {
669 output.put_slice(prefix.as_bytes());
670 output.put_u8(b':');
671 output.put_slice(local_name.as_bytes());
672 prefix.with_suffix(local_name)
673 }
674 None => {
675 output.put_slice(local_name.as_bytes());
676 local_name.to_name()
677 }
678 };
679 self.qname_stack.push(qname);
680 if let Some(name) = self.ns.new_default_declaration() {
681 Self::encode_nsdecl(None, name, output)?;
682 }
683 for (name, prefix) in self.ns.new_prefix_declarations() {
684 Self::encode_nsdecl(Some(prefix), name, output)?;
686 }
687 self.state = EncoderState::ElementHead;
688 Ok(())
689 }
690 _ => Err(Error::UnexpectedToken(self.state.ctx(), item.name(), None)),
691 },
692 Item::Attribute(ref nsuri, local_name, value) => match self.state {
693 EncoderState::ElementHead => {
694 match nsuri.as_namespace_name() {
695 Some(v) => {
696 let (new, prefix) = self
697 .ns
698 .declare_with_auto_prefix(nsuri.clone().into_static());
699 if new {
700 Self::encode_nsdecl(Some(prefix), v, output)?;
701 }
702 output.put_u8(b' ');
703 output.put_slice(prefix.as_bytes());
704 output.put_u8(b':');
705 output.put_slice(local_name.as_bytes());
706 }
707 None => {
708 output.put_u8(b' ');
709 output.put_slice(local_name.as_bytes());
710 }
711 }
712 output.put_u8(b'=');
713 output.put_u8(b'\'');
714 escape_text(output, value, true)?;
715 output.put_u8(b'\'');
716 Ok(())
717 }
718 _ => Err(Error::UnexpectedToken(self.state.ctx(), item.name(), None)),
719 },
720 Item::ElementHeadEnd => match self.state {
721 EncoderState::ElementHead => {
722 output.put_u8(b'>');
723 self.ns.push();
724 self.state = EncoderState::Content;
725 Ok(())
726 }
727 _ => Err(Error::UnexpectedToken(self.state.ctx(), item.name(), None)),
728 },
729 Item::Text(cdata) => match self.state {
730 EncoderState::Content => {
731 escape_text(output, cdata, false)?;
732 Ok(())
733 }
734 _ => Err(Error::UnexpectedToken(self.state.ctx(), item.name(), None)),
735 },
736 Item::ElementFoot => match self.state {
737 EncoderState::Content => {
738 self.ns.pop();
739 output.put_slice(b"</");
740 output.put_slice(self.qname_stack.pop().unwrap().as_bytes());
741 output.put_u8(b'>');
742 if self.qname_stack.is_empty() {
743 self.state = EncoderState::EndOfDocument
744 }
745 Ok(())
746 }
747 EncoderState::ElementHead => {
748 output.put_slice(b"/>");
749 self.ns.push();
750 self.ns.pop();
751 self.qname_stack.pop();
752 if self.qname_stack.is_empty() {
753 self.state = EncoderState::EndOfDocument
754 } else {
755 self.state = EncoderState::Content;
756 }
757 Ok(())
758 }
759 _ => Err(Error::UnexpectedToken(self.state.ctx(), item.name(), None)),
760 },
761 }
762 }
763
764 pub fn encode_into_bytes(&mut self, item: Item<'_>, output: &mut BytesMut) -> Result<()> {
778 self.encode(item, output)
779 }
780
781 pub fn encode_event<O: BufMut>(&mut self, ev: &Event, output: &mut O) -> Result<()> {
788 match ev {
789 Event::XmlDeclaration(_, version) => {
790 self.encode(Item::XmlDeclaration(*version), output)?;
791 }
792 Event::StartElement(_, (ns, name), attrs) => {
793 self.encode(Item::ElementHeadStart(ns.borrow(), name.as_ref()), output)?;
794 for ((ns, name), v) in attrs.iter() {
795 self.encode(Item::Attribute(ns.borrow(), name.as_ref(), v), output)?
796 }
797 self.encode(Item::ElementHeadEnd, output)?;
798 }
799 Event::EndElement(_) => self.encode(Item::ElementFoot, output)?,
800 Event::Text(_, text) => self.encode(Item::Text(text.as_ref()), output)?,
801 }
802 Ok(())
803 }
804
805 pub fn encode_event_into_bytes(&mut self, ev: &Event, output: &mut BytesMut) -> Result<()> {
812 self.encode_event(ev, output)
813 }
814}
815
816#[cfg(test)]
817mod tests_simple_namespaces {
818 use super::*;
819
820 fn ns1() -> Namespace<'static> {
821 Namespace::try_from("uri:foo").unwrap()
822 }
823
824 fn ns2() -> Namespace<'static> {
825 Namespace::try_from("uri:bar").unwrap()
826 }
827
828 fn ns3() -> Namespace<'static> {
829 Namespace::try_from("uri:baz").unwrap()
830 }
831
832 fn mk() -> SimpleNamespaces {
833 SimpleNamespaces::new()
834 }
835
836 #[test]
837 fn prefers_setting_default_namespace() {
838 let mut ns = mk();
839 let (new, prefix) = ns.declare_auto(ns1());
840 assert!(new);
841 assert!(prefix.is_none());
842 }
843
844 #[test]
845 fn unset_namespace_is_not_new_initially() {
846 let mut ns = mk();
847 let (new, prefix) = ns.declare_auto(Namespace::NONE);
848 assert!(prefix.is_none());
849 assert!(!new);
850 }
851
852 #[test]
853 fn predefined_prefixes_can_be_looked_up() {
854 let ns = mk();
855 assert_eq!(ns.lookup_prefix(Some(PREFIX_XML)).unwrap(), XMLNS_XML);
856 assert_eq!(ns.lookup_prefix(Some(PREFIX_XMLNS)).unwrap(), XMLNS_XMLNS);
857 }
858
859 #[test]
860 fn hardcoded_xmlns_namespace_for_declare_auto() {
861 let mut ns = mk();
862 let (new, prefix) = ns.declare_auto(Namespace::XMLNS);
863 assert!(!new);
864 assert!(prefix.unwrap() == PREFIX_XMLNS);
865 }
866
867 #[test]
868 fn hardcoded_xml_namespace_for_declare_auto() {
869 let mut ns = mk();
870 let (new, prefix) = ns.declare_auto(Namespace::XML);
871 assert!(!new);
872 assert!(prefix.unwrap() == PREFIX_XML);
873 }
874
875 #[test]
876 fn hardcoded_xmlns_namespace_for_declare_with_auto_prefix() {
877 let mut ns = mk();
878 let (new, prefix) = ns.declare_with_auto_prefix(Namespace::XMLNS);
879 assert!(!new);
880 assert!(prefix == "xmlns");
881 }
882
883 #[test]
884 fn hardcoded_xml_namespace_for_declare_with_auto_prefix() {
885 let mut ns = mk();
886 let (new, prefix) = ns.declare_with_auto_prefix(Namespace::XML);
887 assert!(!new);
888 assert!(prefix == "xml");
889 }
890
891 #[test]
892 fn hardcoded_xmlns_namespace_for_declare_fixed() {
893 let mut ns = mk();
894 let new = ns.declare_fixed(Some(PREFIX_XMLNS), Namespace::XMLNS);
895 assert!(!new);
896 }
897
898 #[test]
899 fn hardcoded_xml_namespace_for_declare_fixed() {
900 let mut ns = mk();
901 let new = ns.declare_fixed(Some(PREFIX_XML), Namespace::XML);
902 assert!(!new);
903 }
904
905 #[test]
906 #[should_panic(expected = "xml is a reserved prefix")]
907 fn reject_xml_as_fixed_prefix_for_random_namespace() {
908 let mut ns = mk();
909 ns.declare_fixed(Some(PREFIX_XML), ns1());
910 }
911
912 #[test]
913 #[should_panic(expected = "xmlns is a reserved prefix")]
914 fn reject_xmlns_fixed_prefix_for_random_namespace() {
915 let mut ns = mk();
916 ns.declare_fixed(Some(PREFIX_XMLNS), ns1());
917 }
918
919 #[test]
920 #[should_panic(expected = "must be bound to xml prefix")]
921 fn reject_xml_namespace_with_other_prefix() {
922 let mut ns = mk();
923 ns.declare_fixed(Some("foo".try_into().unwrap()), Namespace::XML);
924 }
925
926 #[test]
927 #[should_panic(expected = "must be bound to xmlns prefix")]
928 fn reject_xmlns_namespace_with_other_prefix() {
929 let mut ns = mk();
930 ns.declare_fixed(Some("foo".try_into().unwrap()), Namespace::XMLNS);
931 }
932
933 #[test]
934 fn retrieve_default_namespace() {
935 let mut ns = mk();
936 ns.declare_auto(ns1());
937 match ns.get_prefix_or_default(ns1()) {
938 Ok(None) => {}
939 other => panic!("unexpected get_prefix_or_default result: {:?}", other),
940 };
941 match ns.lookup_prefix(None) {
942 Ok(name) => {
943 assert_eq!(name, ns1());
944 }
945 other => panic!("unexpected lookup_prefix result: {:?}", other),
946 }
947 }
948
949 #[test]
950 fn declaration_causes_lookup_to_return_a_thing() {
951 let mut ns = mk();
952 match ns.lookup_prefix(None) {
953 Err(PrefixError::Undeclared) => (),
954 other => panic!("unexpected lookup_prefix result: {:?}", other),
955 }
956 ns.declare_auto(ns1());
957 match ns.lookup_prefix(None) {
958 Ok(name) => {
959 assert_eq!(name, ns1());
960 }
961 other => panic!("unexpected lookup_prefix result: {:?}", other),
962 }
963 }
964
965 #[test]
966 fn reuses_existing_declaration_if_available() {
967 let mut ns = mk();
968 ns.declare_auto(ns1());
969 let (new, prefix) = ns.declare_auto(ns1());
970 assert!(!new);
971 assert!(prefix.is_none());
972 }
973
974 #[test]
975 fn allocates_prefix_if_default_is_already_set() {
976 let mut ns = mk();
977 ns.declare_auto(ns1());
978 let (new, prefix) = ns.declare_auto(ns2());
979 assert!(new);
980 assert!(prefix.is_some());
981 }
982
983 #[test]
984 fn retrieve_prefixed_namespace() {
985 let mut ns = mk();
986 let prefix = ns.declare_with_auto_prefix(ns1()).1.to_ncname();
987 match ns.get_prefix_or_default(ns1()) {
988 Ok(Some(v)) => {
989 assert_eq!(v, prefix);
990 }
991 other => panic!("unexpected get_prefix_or_default result: {:?}", other),
992 };
993 }
994
995 #[test]
996 fn declaration_causes_lookup_to_return_a_thing_for_a_prefix() {
997 let mut ns = mk();
998 match ns.lookup_prefix(None) {
999 Err(PrefixError::Undeclared) => (),
1000 other => panic!("unexpected lookup_prefix result: {:?}", other),
1001 }
1002 let prefix = ns.declare_with_auto_prefix(ns1()).1.to_ncname();
1003 match ns.lookup_prefix(Some(&prefix)) {
1004 Ok(name) => {
1005 assert_eq!(name, ns1());
1006 }
1007 other => panic!("unexpected lookup_prefix result: {:?}", other),
1008 }
1009 match ns.lookup_prefix(None) {
1010 Err(PrefixError::Undeclared) => (),
1011 other => panic!("unexpected lookup_prefix result: {:?}", other),
1012 }
1013 }
1014
1015 #[test]
1016 fn reuses_auto_allocated_prefix_for_same_ns() {
1017 let mut ns = mk();
1018 let prefix1 = ns.declare_with_auto_prefix(ns1()).1.to_ncname();
1019 let prefix2 = ns.declare_with_auto_prefix(ns1()).1.to_ncname();
1020 assert_eq!(prefix1, prefix2);
1021 }
1022
1023 #[test]
1024 fn auto_allocates_different_prefixes_for_different_ns() {
1025 let mut ns = mk();
1026 let prefix1 = ns.declare_with_auto_prefix(ns1()).1.to_ncname();
1027 let prefix2 = ns.declare_with_auto_prefix(ns2()).1.to_ncname();
1028 assert_ne!(prefix1, prefix2);
1029 }
1030
1031 #[test]
1032 fn preserves_default_ns_across_elements() {
1033 let mut ns = mk();
1034 ns.declare_auto(ns1());
1035 ns.get_prefix_or_default(ns1()).unwrap();
1036 ns.push();
1037 let (new, prefix) = ns.declare_auto(ns1());
1038 assert!(!new);
1039 assert!(prefix.is_none());
1040 assert!(ns.get_prefix_or_default(ns1()).unwrap().is_none());
1041 match ns.lookup_prefix(None) {
1042 Ok(name) => {
1043 assert_eq!(name, ns1());
1044 }
1045 other => panic!("unexpected lookup_prefix result: {:?}", other),
1046 }
1047 }
1048
1049 #[test]
1050 fn declare_with_fixed_prefix() {
1051 let mut ns = mk();
1052 ns.declare_fixed(Some(NcNameStr::from_str("stream").unwrap()), ns1());
1053 match ns.get_prefix(ns1()) {
1054 Ok(v) => {
1055 assert_eq!(v, "stream");
1056 }
1057 other => panic!("unexpected get_prefix result: {:?}", other),
1058 }
1059 match ns.get_prefix_or_default(ns1()) {
1060 Ok(Some(v)) => {
1061 assert_eq!(v, "stream");
1062 }
1063 other => panic!("unexpected get_prefix result: {:?}", other),
1064 }
1065 }
1066
1067 #[test]
1068 fn declare_fixed_prefixless() {
1069 let mut ns = mk();
1070 ns.declare_fixed(None, ns1());
1071 match ns.get_prefix_or_default(ns1()) {
1072 Ok(None) => (),
1073 other => panic!("unexpected get_prefix result: {:?}", other),
1074 }
1075 match ns.get_prefix(ns1()) {
1076 Err(PrefixError::Undeclared) => (),
1077 other => panic!("unexpected get_prefix result: {:?}", other),
1078 }
1079 }
1080
1081 #[test]
1082 fn preserves_global_prefixed_across_elements() {
1083 let mut ns = mk();
1084 ns.declare_fixed(Some(NcNameStr::from_str("stream").unwrap()), ns1());
1085 ns.declare_fixed(None, ns2());
1086 ns.push();
1087 match ns.get_prefix(ns1()) {
1088 Ok(v) => {
1089 assert_eq!(v, "stream");
1090 }
1091 other => panic!("unexpected get_prefix result: {:?}", other),
1092 }
1093 match ns.get_prefix_or_default(ns1()) {
1094 Ok(Some(v)) => {
1095 assert_eq!(v, "stream");
1096 }
1097 other => panic!("unexpected get_prefix result: {:?}", other),
1098 }
1099 match ns.get_prefix_or_default(ns2()) {
1100 Ok(None) => (),
1101 other => panic!("unexpected get_prefix result: {:?}", other),
1102 }
1103 match ns.get_prefix(ns2()) {
1104 Err(PrefixError::Undeclared) => (),
1105 other => panic!("unexpected get_prefix result: {:?}", other),
1106 }
1107 }
1108
1109 #[test]
1110 #[should_panic(expected = "conflict")]
1111 fn prohibits_overriding_global_prefix() {
1112 let mut ns = mk();
1113 ns.declare_fixed(Some(NcNameStr::from_str("stream").unwrap()), ns1());
1114 ns.declare_fixed(None, ns2());
1115 ns.push();
1116 ns.declare_fixed(Some(NcNameStr::from_str("stream").unwrap()), ns2());
1117 }
1118
1119 #[test]
1120 fn auto_allocations_stay_global_and_do_not_cause_conflicts() {
1121 let mut ns = mk();
1122 let prefix1 = ns.declare_with_auto_prefix(ns1()).1.to_ncname();
1123 let prefix2 = ns.declare_with_auto_prefix(ns2()).1.to_ncname();
1124 ns.push();
1125 let (new, prefix3) = ns.declare_with_auto_prefix(ns3());
1126 assert!(new);
1127 let prefix3 = prefix3.to_ncname();
1128 assert_ne!(prefix1, prefix3);
1129 assert_ne!(prefix2, prefix3);
1130 }
1131
1132 #[test]
1133 #[should_panic(expected = "conflict")]
1134 fn fixed_global_decl_can_conflict_with_auto_decl() {
1135 let mut ns = mk();
1136 ns.declare_fixed(Some(NcNameStr::from_str("tns0").unwrap()), ns1());
1137 ns.push();
1138 ns.declare_with_auto_prefix(ns3());
1139 }
1140
1141 #[test]
1142 #[should_panic(expected = "conflict")]
1143 fn fixed_local_decl_can_conflict_with_auto_decl() {
1144 let mut ns = mk();
1145 ns.declare_fixed(Some(NcNameStr::from_str("tns0").unwrap()), ns1());
1146 ns.declare_with_auto_prefix(ns3());
1147 }
1148}
1149
1150#[cfg(test)]
1151mod tests_encoder {
1152 use alloc::string::String;
1153 use std::io;
1154 use std::println;
1155
1156 use super::*;
1157
1158 use crate::parser::EventMetrics;
1159
1160 fn mkencoder() -> Encoder<SimpleNamespaces> {
1161 Encoder::new()
1162 }
1163
1164 fn ns1() -> Namespace<'static> {
1165 Namespace::try_from("uri:foo").unwrap()
1166 }
1167
1168 fn ns2() -> Namespace<'static> {
1169 Namespace::try_from("uri:bar").unwrap()
1170 }
1171
1172 fn ns3() -> Namespace<'static> {
1173 Namespace::try_from("uri:baz").unwrap()
1174 }
1175
1176 fn parse(mut input: &[u8]) -> (Vec<Event>, io::Result<bool>) {
1177 let mut parser: crate::Reader<_> = crate::Reader::new(&mut input);
1178 let mut events = Vec::new();
1179 let result = crate::as_eof_flag(parser.read_all(|ev| events.push(ev)));
1180 (events, result)
1181 }
1182
1183 fn encode_events(evs: &[Event]) -> Result<BytesMut> {
1184 let mut out = BytesMut::new();
1185 let mut encoder = mkencoder();
1186 for ev in evs {
1187 encoder.encode_event(&ev, &mut out)?;
1188 }
1189 Ok(out)
1190 }
1191
1192 fn encode_events_via_into_bytes(evs: &[Event]) -> Result<BytesMut> {
1193 let mut out = BytesMut::new();
1194 let mut encoder = mkencoder();
1195 for ev in evs {
1196 encoder.encode_event_into_bytes(&ev, &mut out)?;
1197 }
1198 Ok(out)
1199 }
1200
1201 fn collapse_cdata(evs: &mut Vec<Event>) {
1202 let mut buf = Vec::new();
1203 core::mem::swap(&mut buf, evs);
1204 let mut cdata_hold = None;
1205 for event in buf.drain(..) {
1206 match event {
1207 Event::Text(_, txt) => match cdata_hold.take() {
1208 None => cdata_hold = Some(txt),
1209 Some(existing) => cdata_hold = Some(existing + &*txt),
1210 },
1211 _ => {
1212 match cdata_hold.take() {
1213 Some(txt) => evs.push(Event::Text(EventMetrics::new(0), txt)),
1214 None => (),
1215 };
1216 evs.push(event);
1217 }
1218 }
1219 }
1220 match cdata_hold.take() {
1221 Some(txt) => evs.push(Event::Text(EventMetrics::new(0), txt)),
1222 None => (),
1223 };
1224 }
1225
1226 fn assert_event_eq(a: &Event, b: &Event) {
1227 match (a, b) {
1228 (Event::XmlDeclaration(_, v1), Event::XmlDeclaration(_, v2)) => {
1229 assert_eq!(v1, v2);
1230 }
1231 (Event::StartElement(_, name1, attrs1), Event::StartElement(_, name2, attrs2)) => {
1232 assert_eq!(name1, name2);
1233 assert_eq!(attrs1, attrs2);
1234 }
1235 (Event::EndElement(_), Event::EndElement(_)) => {}
1236 (Event::Text(_, text1), Event::Text(_, text2)) => {
1237 assert_eq!(text1, text2);
1238 }
1239 (a, b) => panic!("event types differ: {:?} != {:?}", a, b),
1241 }
1242 }
1243
1244 fn assert_events_eq(initial: &[Event], reparsed: &[Event]) {
1245 for (a, b) in initial.iter().zip(reparsed.iter()) {
1246 assert_event_eq(a, b);
1247 }
1248 if initial.len() > reparsed.len() {
1249 panic!(
1250 "missing {} events in reparsed version",
1251 initial.len() - reparsed.len()
1252 )
1253 }
1254 if reparsed.len() > initial.len() {
1255 panic!(
1256 "{} additional events in reparsed version: {:?}",
1257 reparsed.len() - initial.len(),
1258 &reparsed[initial.len()..]
1259 )
1260 }
1261 }
1262
1263 fn check_reserialized(
1264 input: &[u8],
1265 initial: &[Event],
1266 initial_eof: bool,
1267 reserialized: &[u8],
1268 via: &'static str,
1269 ) {
1270 let (mut reparsed, reparsed_result) = parse(&reserialized[..]);
1271 collapse_cdata(&mut reparsed);
1272 let reparsed_eof = match reparsed_result {
1273 Ok(eof) => eof,
1274 Err(e) => {
1275 panic!(
1276 "reserialized (via {}) XML\n\n{:?}\n\n of\n\n{:?}\n\nfails to parse: {}",
1277 via,
1278 String::from_utf8_lossy(&reserialized[..]),
1279 String::from_utf8_lossy(input),
1280 e
1281 )
1282 }
1283 };
1284 println!("checking (via {})", via);
1285 println!(
1286 "reserialized: {:?}",
1287 String::from_utf8_lossy(&reserialized[..])
1288 );
1289 assert_events_eq(initial, &reparsed);
1290 assert_eq!(initial_eof, reparsed_eof);
1291 }
1292
1293 fn roundtrip_test(input: &[u8]) {
1294 let (mut initial, initial_result) = parse(input);
1296 collapse_cdata(&mut initial);
1297 let initial_eof = initial_result.expect("test input must parse correctly");
1298 let reserialized_via_buf =
1299 encode_events(&initial[..]).expect("parsed input must be encodable");
1300 let reserialized_via_bytes =
1301 encode_events_via_into_bytes(&initial[..]).expect("parsed input must be encodable");
1302 check_reserialized(
1303 input,
1304 &initial,
1305 initial_eof,
1306 &reserialized_via_buf[..],
1307 "buf",
1308 );
1309 check_reserialized(
1310 input,
1311 &initial,
1312 initial_eof,
1313 &reserialized_via_bytes[..],
1314 "bytes",
1315 );
1316 }
1317
1318 #[test]
1319 fn reject_duplicate_xml_declaration() {
1320 let mut enc = mkencoder();
1321 let mut buf = BytesMut::new();
1322 match enc.encode(Item::XmlDeclaration(XmlVersion::V1_0), &mut buf) {
1323 Ok(()) => (),
1324 other => panic!("unexpected encode result: {:?}", other),
1325 };
1326 match enc.encode(Item::XmlDeclaration(XmlVersion::V1_0), &mut buf) {
1327 Err(Error::UnexpectedToken(_, "xml declaration", _)) => (),
1328 other => panic!("unexpected encode result: {:?}", other),
1329 };
1330 }
1331
1332 #[test]
1333 fn reject_text_at_global_level() {
1334 let mut enc = mkencoder();
1335 let mut buf = BytesMut::new();
1336 match enc.encode(Item::Text("".try_into().unwrap()), &mut buf) {
1337 Err(Error::UnexpectedToken(_, "text", _)) => (),
1338 other => panic!("unexpected encode result: {:?}", other),
1339 };
1340 }
1341
1342 #[test]
1343 fn reject_attribute_at_global_level() {
1344 let mut enc = mkencoder();
1345 let mut buf = BytesMut::new();
1346 match enc.encode(
1347 Item::Attribute(
1348 Namespace::NONE,
1349 "x".try_into().unwrap(),
1350 "".try_into().unwrap(),
1351 ),
1352 &mut buf,
1353 ) {
1354 Err(Error::UnexpectedToken(_, "attribute", _)) => (),
1355 other => panic!("unexpected encode result: {:?}", other),
1356 };
1357 }
1358
1359 #[test]
1360 fn allow_element_before_decl() {
1361 let mut enc = mkencoder();
1362 let mut buf = BytesMut::new();
1363 match enc.encode(
1364 Item::ElementHeadStart(Namespace::NONE, "x".try_into().unwrap()),
1365 &mut buf,
1366 ) {
1367 Ok(()) => (),
1368 other => panic!("unexpected encode result: {:?}", other),
1369 };
1370 }
1371
1372 #[test]
1373 fn reject_xml_decl_in_element() {
1374 let mut enc = mkencoder();
1375 let mut buf = BytesMut::new();
1376 match enc.encode(
1377 Item::ElementHeadStart(Namespace::NONE, "x".try_into().unwrap()),
1378 &mut buf,
1379 ) {
1380 Ok(()) => (),
1381 other => panic!("unexpected encode result: {:?}", other),
1382 };
1383 match enc.encode(Item::XmlDeclaration(XmlVersion::V1_0), &mut buf) {
1384 Err(Error::UnexpectedToken(_, "xml declaration", _)) => (),
1385 other => panic!("unexpected encode result: {:?}", other),
1386 };
1387 }
1388
1389 #[test]
1390 fn encode_self_closed_tag() {
1391 let mut enc = mkencoder();
1392 let mut buf = BytesMut::new();
1393 match enc.encode(
1394 Item::ElementHeadStart(Namespace::NONE, "x".try_into().unwrap()),
1395 &mut buf,
1396 ) {
1397 Ok(()) => (),
1398 other => panic!("unexpected encode result: {:?}", other),
1399 };
1400 match enc.encode(Item::ElementFoot, &mut buf) {
1401 Ok(()) => (),
1402 other => panic!("unexpected encode result: {:?}", other),
1403 };
1404 assert_eq!(&buf, &b"<x/>"[..]);
1405 }
1406
1407 #[test]
1408 fn encode_root_prefix() {
1409 let mut enc = mkencoder();
1410 let mut buf = BytesMut::new();
1411 enc.ns.declare_fixed(Some("foo".try_into().unwrap()), ns1());
1412 match enc.encode(
1413 Item::ElementHeadStart(ns1(), "x".try_into().unwrap()),
1414 &mut buf,
1415 ) {
1416 Ok(()) => (),
1417 other => panic!("unexpected encode result: {:?}", other),
1418 };
1419 match enc.encode(Item::ElementFoot, &mut buf) {
1420 Ok(()) => (),
1421 other => panic!("unexpected encode result: {:?}", other),
1422 };
1423 assert_eq!(&buf, &b"<foo:x xmlns:foo='uri:foo'/>"[..]);
1424 }
1425
1426 #[test]
1427 fn use_explicitly_set_at_root() {
1428 let mut enc = mkencoder();
1429 let mut buf = BytesMut::new();
1430 enc.ns.declare_fixed(Some("foo".try_into().unwrap()), ns1());
1431 match enc.encode(
1432 Item::ElementHeadStart(ns2(), "x".try_into().unwrap()),
1433 &mut buf,
1434 ) {
1435 Ok(()) => (),
1436 other => panic!("unexpected encode result: {:?}", other),
1437 };
1438 match enc.encode(Item::ElementHeadEnd, &mut buf) {
1439 Ok(()) => (),
1440 other => panic!("unexpected encode result: {:?}", other),
1441 };
1442 match enc.encode(
1443 Item::ElementHeadStart(ns1(), "y".try_into().unwrap()),
1444 &mut buf,
1445 ) {
1446 Ok(()) => (),
1447 other => panic!("unexpected encode result: {:?}", other),
1448 };
1449 match enc.encode(Item::ElementFoot, &mut buf) {
1450 Ok(()) => (),
1451 other => panic!("unexpected encode result: {:?}", other),
1452 };
1453 match enc.encode(Item::ElementFoot, &mut buf) {
1454 Ok(()) => (),
1455 other => panic!("unexpected encode result: {:?}", other),
1456 };
1457 assert_eq!(
1458 &buf,
1459 &b"<x xmlns='uri:bar' xmlns:foo='uri:foo'><foo:y/></x>"[..]
1460 );
1461 }
1462
1463 #[test]
1464 fn do_not_emit_duplicate_declarations() {
1465 let mut enc = mkencoder();
1466 let mut buf = BytesMut::new();
1467 enc.ns.declare_fixed(Some("foo".try_into().unwrap()), ns1());
1468 match enc.encode(
1469 Item::ElementHeadStart(ns2(), "x".try_into().unwrap()),
1470 &mut buf,
1471 ) {
1472 Ok(()) => (),
1473 other => panic!("unexpected encode result: {:?}", other),
1474 };
1475 match enc.encode(
1476 Item::Attribute(ns1(), "a1".try_into().unwrap(), "v1".try_into().unwrap()),
1477 &mut buf,
1478 ) {
1479 Ok(()) => (),
1480 other => panic!("unexpected encode result: {:?}", other),
1481 }
1482 match enc.encode(
1483 Item::Attribute(ns1(), "a2".try_into().unwrap(), "v2".try_into().unwrap()),
1484 &mut buf,
1485 ) {
1486 Ok(()) => (),
1487 other => panic!("unexpected encode result: {:?}", other),
1488 }
1489 match enc.encode(
1490 Item::Attribute(ns2(), "a3".try_into().unwrap(), "v3".try_into().unwrap()),
1491 &mut buf,
1492 ) {
1493 Ok(()) => (),
1494 other => panic!("unexpected encode result: {:?}", other),
1495 }
1496 match enc.encode(
1497 Item::Attribute(ns2(), "a4".try_into().unwrap(), "v4".try_into().unwrap()),
1498 &mut buf,
1499 ) {
1500 Ok(()) => (),
1501 other => panic!("unexpected encode result: {:?}", other),
1502 }
1503 match enc.encode(
1504 Item::Attribute(ns3(), "a5".try_into().unwrap(), "v5".try_into().unwrap()),
1505 &mut buf,
1506 ) {
1507 Ok(()) => (),
1508 other => panic!("unexpected encode result: {:?}", other),
1509 }
1510 match enc.encode(
1511 Item::Attribute(ns3(), "a6".try_into().unwrap(), "v6".try_into().unwrap()),
1512 &mut buf,
1513 ) {
1514 Ok(()) => (),
1515 other => panic!("unexpected encode result: {:?}", other),
1516 }
1517 match enc.encode(Item::ElementHeadEnd, &mut buf) {
1518 Ok(()) => (),
1519 other => panic!("unexpected encode result: {:?}", other),
1520 };
1521 match enc.encode(
1522 Item::ElementHeadStart(ns1(), "y".try_into().unwrap()),
1523 &mut buf,
1524 ) {
1525 Ok(()) => (),
1526 other => panic!("unexpected encode result: {:?}", other),
1527 };
1528 match enc.encode(Item::ElementFoot, &mut buf) {
1529 Ok(()) => (),
1530 other => panic!("unexpected encode result: {:?}", other),
1531 };
1532 match enc.encode(Item::ElementFoot, &mut buf) {
1533 Ok(()) => (),
1534 other => panic!("unexpected encode result: {:?}", other),
1535 };
1536 assert_eq!(&buf, &b"<x xmlns='uri:bar' xmlns:foo='uri:foo' foo:a1='v1' foo:a2='v2' xmlns:tns0='uri:bar' tns0:a3='v3' tns0:a4='v4' xmlns:tns1='uri:baz' tns1:a5='v5' tns1:a6='v6'><foo:y/></x>"[..]);
1537 }
1538
1539 #[test]
1540 fn reuses_existing_declaration_for_nested_namespaced_attributes_if_available() {
1541 let mut enc = mkencoder();
1542 let mut buf = BytesMut::new();
1543 enc.ns.declare_fixed(Some("foo".try_into().unwrap()), ns1());
1544 match enc.encode(
1545 Item::ElementHeadStart(ns2(), "x".try_into().unwrap()),
1546 &mut buf,
1547 ) {
1548 Ok(()) => (),
1549 other => panic!("unexpected encode result: {:?}", other),
1550 };
1551 match enc.encode(
1552 Item::Attribute(ns1(), "a1".try_into().unwrap(), "v1".try_into().unwrap()),
1553 &mut buf,
1554 ) {
1555 Ok(()) => (),
1556 other => panic!("unexpected encode result: {:?}", other),
1557 }
1558 match enc.encode(
1559 Item::Attribute(ns1(), "a2".try_into().unwrap(), "v2".try_into().unwrap()),
1560 &mut buf,
1561 ) {
1562 Ok(()) => (),
1563 other => panic!("unexpected encode result: {:?}", other),
1564 }
1565 match enc.encode(
1566 Item::Attribute(ns2(), "a3".try_into().unwrap(), "v3".try_into().unwrap()),
1567 &mut buf,
1568 ) {
1569 Ok(()) => (),
1570 other => panic!("unexpected encode result: {:?}", other),
1571 }
1572 match enc.encode(
1573 Item::Attribute(ns2(), "a4".try_into().unwrap(), "v4".try_into().unwrap()),
1574 &mut buf,
1575 ) {
1576 Ok(()) => (),
1577 other => panic!("unexpected encode result: {:?}", other),
1578 }
1579 match enc.encode(
1580 Item::Attribute(ns3(), "a5".try_into().unwrap(), "v5".try_into().unwrap()),
1581 &mut buf,
1582 ) {
1583 Ok(()) => (),
1584 other => panic!("unexpected encode result: {:?}", other),
1585 }
1586 match enc.encode(
1587 Item::Attribute(ns3(), "a6".try_into().unwrap(), "v6".try_into().unwrap()),
1588 &mut buf,
1589 ) {
1590 Ok(()) => (),
1591 other => panic!("unexpected encode result: {:?}", other),
1592 }
1593 match enc.encode(Item::ElementHeadEnd, &mut buf) {
1594 Ok(()) => (),
1595 other => panic!("unexpected encode result: {:?}", other),
1596 };
1597 match enc.encode(
1598 Item::ElementHeadStart(ns1(), "y".try_into().unwrap()),
1599 &mut buf,
1600 ) {
1601 Ok(()) => (),
1602 other => panic!("unexpected encode result: {:?}", other),
1603 };
1604 match enc.encode(
1605 Item::Attribute(ns1(), "a1".try_into().unwrap(), "v1".try_into().unwrap()),
1606 &mut buf,
1607 ) {
1608 Ok(()) => (),
1609 other => panic!("unexpected encode result: {:?}", other),
1610 }
1611 match enc.encode(Item::ElementFoot, &mut buf) {
1612 Ok(()) => (),
1613 other => panic!("unexpected encode result: {:?}", other),
1614 };
1615 match enc.encode(Item::ElementFoot, &mut buf) {
1616 Ok(()) => (),
1617 other => panic!("unexpected encode result: {:?}", other),
1618 };
1619 assert_eq!(&buf, &b"<x xmlns='uri:bar' xmlns:foo='uri:foo' foo:a1='v1' foo:a2='v2' xmlns:tns0='uri:bar' tns0:a3='v3' tns0:a4='v4' xmlns:tns1='uri:baz' tns1:a5='v5' tns1:a6='v6'><foo:y foo:a1='v1'/></x>"[..]);
1620 }
1621
1622 #[test]
1623 fn self_closed_tag_encoding_ends_document_if_it_closes_the_root() {
1624 let mut enc = mkencoder();
1625 let mut buf = BytesMut::new();
1626 match enc.encode(
1627 Item::ElementHeadStart(Namespace::NONE, "x".try_into().unwrap()),
1628 &mut buf,
1629 ) {
1630 Ok(()) => (),
1631 other => panic!("unexpected encode result: {:?}", other),
1632 };
1633 match enc.encode(Item::ElementFoot, &mut buf) {
1634 Ok(()) => (),
1635 other => panic!("unexpected encode result: {:?}", other),
1636 };
1637 match enc.encode(Item::Text("".try_into().unwrap()), &mut buf) {
1638 Err(Error::UnexpectedToken(Some(ErrorContext::DocumentEnd), "text", _)) => (),
1639 other => panic!("unexpected encode result: {:?}", other),
1640 };
1641 }
1642
1643 #[test]
1644 fn self_closed_tag_encoding_allows_content_thereafter() {
1645 let mut enc = mkencoder();
1646 let mut buf = BytesMut::new();
1647 match enc.encode(
1648 Item::ElementHeadStart(Namespace::NONE, "x".try_into().unwrap()),
1649 &mut buf,
1650 ) {
1651 Ok(()) => (),
1652 other => panic!("unexpected encode result: {:?}", other),
1653 };
1654 match enc.encode(Item::ElementHeadEnd, &mut buf) {
1655 Ok(()) => (),
1656 other => panic!("unexpected encode result: {:?}", other),
1657 };
1658 match enc.encode(
1659 Item::ElementHeadStart(Namespace::NONE, "y".try_into().unwrap()),
1660 &mut buf,
1661 ) {
1662 Ok(()) => (),
1663 other => panic!("unexpected encode result: {:?}", other),
1664 };
1665 match enc.encode(Item::ElementFoot, &mut buf) {
1666 Ok(()) => (),
1667 other => panic!("unexpected encode result: {:?}", other),
1668 };
1669 match enc.encode(Item::Text("foo".try_into().unwrap()), &mut buf) {
1670 Ok(()) => (),
1671 other => panic!("unexpected encode result: {:?}", other),
1672 };
1673 assert_eq!(&buf[..], b"<x><y/>foo");
1674 }
1675
1676 #[test]
1677 fn reject_element_after_end_of_document() {
1678 let mut enc = mkencoder();
1679 let mut buf = BytesMut::new();
1680 match enc.encode(
1681 Item::ElementHeadStart(Namespace::NONE, "x".try_into().unwrap()),
1682 &mut buf,
1683 ) {
1684 Ok(()) => (),
1685 other => panic!("unexpected encode result: {:?}", other),
1686 };
1687 match enc.encode(Item::ElementHeadEnd, &mut buf) {
1688 Ok(()) => (),
1689 other => panic!("unexpected encode result: {:?}", other),
1690 };
1691 match enc.encode(Item::ElementFoot, &mut buf) {
1692 Ok(()) => (),
1693 other => panic!("unexpected encode result: {:?}", other),
1694 };
1695 match enc.encode(
1696 Item::ElementHeadStart(Namespace::NONE, "x".try_into().unwrap()),
1697 &mut buf,
1698 ) {
1699 Err(Error::UnexpectedToken(Some(ErrorContext::DocumentEnd), "element start", _)) => (),
1700 other => panic!("unexpected encode result: {:?}", other),
1701 };
1702 }
1703
1704 #[test]
1705 fn reject_element_foot_before_start() {
1706 let mut enc = mkencoder();
1707 let mut buf = BytesMut::new();
1708 match enc.encode(Item::ElementFoot, &mut buf) {
1709 Err(Error::UnexpectedToken(_, "element foot", _)) => (),
1710 other => panic!("unexpected encode result: {:?}", other),
1711 };
1712 }
1713
1714 #[test]
1715 fn reject_element_head_end_outside_element_header() {
1716 let mut enc = mkencoder();
1717 let mut buf = BytesMut::new();
1718 match enc.encode(Item::ElementHeadEnd, &mut buf) {
1719 Err(Error::UnexpectedToken(_, "element head end", _)) => (),
1720 other => panic!("unexpected encode result: {:?}", other),
1721 };
1722 match enc.encode(
1723 Item::ElementHeadStart(Namespace::NONE, "x".try_into().unwrap()),
1724 &mut buf,
1725 ) {
1726 Ok(()) => (),
1727 other => panic!("unexpected encode result: {:?}", other),
1728 };
1729 match enc.encode(Item::ElementHeadEnd, &mut buf) {
1730 Ok(()) => (),
1731 other => panic!("unexpected encode result: {:?}", other),
1732 };
1733 match enc.encode(Item::ElementHeadEnd, &mut buf) {
1734 Err(Error::UnexpectedToken(_, "element head end", _)) => (),
1735 other => panic!("unexpected encode result: {:?}", other),
1736 };
1737 }
1738
1739 #[test]
1740 fn reject_text_after_end_of_document() {
1741 let mut enc = mkencoder();
1742 let mut buf = BytesMut::new();
1743 match enc.encode(
1744 Item::ElementHeadStart(Namespace::NONE, "x".try_into().unwrap()),
1745 &mut buf,
1746 ) {
1747 Ok(()) => (),
1748 other => panic!("unexpected encode result: {:?}", other),
1749 };
1750 match enc.encode(Item::ElementHeadEnd, &mut buf) {
1751 Ok(()) => (),
1752 other => panic!("unexpected encode result: {:?}", other),
1753 };
1754 match enc.encode(Item::ElementFoot, &mut buf) {
1755 Ok(()) => (),
1756 other => panic!("unexpected encode result: {:?}", other),
1757 };
1758 match enc.encode(Item::Text("".try_into().unwrap()), &mut buf) {
1759 Err(Error::UnexpectedToken(Some(ErrorContext::DocumentEnd), "text", _)) => (),
1760 other => panic!("unexpected encode result: {:?}", other),
1761 };
1762 }
1763
1764 #[test]
1765 fn single_element_roundtrip() {
1766 roundtrip_test(b"<?xml version='1.0'?>\n<a/>")
1767 }
1768
1769 #[test]
1770 fn nested_element_roundtrip() {
1771 roundtrip_test(b"<?xml version='1.0'?>\n<a><b/></a>")
1772 }
1773
1774 #[test]
1775 fn mixed_content_roundtrip() {
1776 roundtrip_test(b"<?xml version='1.0'?>\n<a>foo<b>bar</b>baz</a>")
1777 }
1778
1779 #[test]
1780 fn text_with_lt_roundtrip() {
1781 roundtrip_test(b"<?xml version='1.0'?>\n<a><</a>")
1782 }
1783
1784 #[test]
1785 fn text_with_gt_roundtrip() {
1786 roundtrip_test(b"<?xml version='1.0'?>\n<a>></a>")
1787 }
1788
1789 #[test]
1790 fn text_with_escaped_entity_roundtrip() {
1791 roundtrip_test(b"<?xml version='1.0'?>\n<a>&amp;</a>")
1792 }
1793
1794 #[test]
1795 fn text_cdata_sequence_roundtrip() {
1796 roundtrip_test(b"<?xml version='1.0'?>\n<a>]]></a>")
1797 }
1798
1799 #[test]
1800 fn attribute_roundtrip() {
1801 roundtrip_test(b"<?xml version='1.0'?>\n<a a1='foo' a2=\"bar\"/>")
1802 }
1803
1804 #[test]
1805 fn attribute_whitespace_roundtrip() {
1806 roundtrip_test(b"<?xml version='1.0'?>\n<a a1='
	 '/>")
1807 }
1808
1809 #[test]
1810 fn attribute_quotes_roundtrip() {
1811 roundtrip_test(b"<?xml version='1.0'?>\n<a a1='"''/>")
1812 }
1813
1814 #[test]
1815 fn namespace_roundtrip() {
1816 roundtrip_test(b"<?xml version='1.0'?>\n<a xmlns='uri:foo'/>")
1817 }
1818
1819 #[test]
1820 fn namespace_roundtrip_builtins() {
1821 roundtrip_test(b"<?xml version='1.0'?>\n<a xml:lang='de'/>")
1822 }
1823
1824 #[test]
1825 fn namespace_roundtrip_with_prefixes() {
1826 roundtrip_test(
1827 b"<?xml version='1.0'?>\n<a xmlns='uri:foo' xmlns:b='uri:bar'><b:b><c/></b:b></a>",
1828 )
1829 }
1830
1831 #[test]
1832 fn roundtrip_escaped_crlf() {
1833 roundtrip_test(b"<?xml version='1.0'?>\n<a>\r\n
</a>")
1834 }
1835
1836 #[test]
1837 fn prefixed_attribute_roundtrip() {
1838 roundtrip_test(
1839 b"<?xml version='1.0'?>\n<a xmlns:b='uri:foo' b:a1='baz' a2='fnord' b:a3='foobar'/>",
1840 )
1841 }
1842
1843 #[test]
1844 fn escape_text_rejects_non_xml_chars() {
1845 let mut buf = String::with_capacity(4);
1846 let mut sink = BytesMut::with_capacity(8);
1847 for cp in 0x0..=0x10ffffu32 {
1848 if let Some(ch) = char::from_u32(cp) {
1849 buf.clear();
1850 buf.push(ch);
1851 let validation = rxml_validation::validate_cdata(&buf);
1852 assert_eq!(
1853 {
1854 sink.clear();
1855 escape_text(&mut sink, &buf, false)
1856 },
1857 validation,
1858 "in non-attribute context",
1859 );
1860 assert_eq!(
1861 {
1862 sink.clear();
1863 escape_text(&mut sink, &buf, true)
1864 },
1865 validation,
1866 "in attribute context",
1867 );
1868 }
1869 }
1870 }
1871}