1use std::borrow::Cow;
2
3use deser_core::de::{
4 self, ContentKey, Deserialize, DeserializeDriver, LexicalRules, deserialize_value,
5};
6use deser_core::{
7 Atom, ContainerShape, Error, ErrorKind, Event, Order, Source, Text, TrackLocations,
8};
9use quick_xml::XmlVersion;
10use quick_xml::events::{BytesRef, BytesStart, Event as XmlEvent};
11use quick_xml::name::{QName, ResolveResult};
12use quick_xml::reader::NsReader;
13
14use crate::Names;
15use crate::mixed::WhitespaceDepths;
16use crate::root::{Declarations, RootData};
17
18#[derive(Debug, Clone, PartialEq, Eq)]
23pub struct DeserializerConfig {
24 pub(crate) names: Names,
25 resolve_namespaces: bool,
26
27 context: deser_core::Context,
28}
29
30impl Default for DeserializerConfig {
31 fn default() -> DeserializerConfig {
32 DeserializerConfig::new()
33 }
34}
35
36impl DeserializerConfig {
37 pub const fn new() -> DeserializerConfig {
39 DeserializerConfig {
40 names: Names::new(),
41 resolve_namespaces: false,
42
43 context: deser_core::Context::new(),
44 }
45 }
46
47 pub const fn builder() -> DeserializerConfigBuilder {
49 DeserializerConfigBuilder::new()
50 }
51
52 pub const fn into_builder(self) -> DeserializerConfigBuilder {
54 DeserializerConfigBuilder { value: self }
55 }
56
57 pub fn set_context(&mut self, context: deser_core::Context) {
65 self.context = context;
66 }
67
68 pub(crate) fn without_context(&self) -> DeserializerConfig {
71 let mut config = self.clone();
72 config.context = deser_core::Context::default();
73 config
74 }
75
76 pub fn context(&self) -> &deser_core::Context {
78 &self.context
79 }
80
81 pub const fn set_attribute_prefix(&mut self, prefix: &'static str) {
85 self.names.attribute_prefix = prefix;
86 }
87
88 pub const fn set_text_key(&mut self, key: &'static str) {
93 self.names.text_key = key;
94 }
95
96 pub const fn namespaces(
131 mut self,
132 namespaces: &'static [(&'static str, &'static str)],
133 ) -> DeserializerConfig {
134 self.names.namespaces = namespaces;
135 self
136 }
137
138 pub const fn set_resolve_namespaces(&mut self, yes: bool) {
184 self.resolve_namespaces = yes;
185 }
186
187 pub fn from_str<'de, T: Deserialize<'de>>(&self, s: &'de str) -> Result<T, Error> {
189 deserialize_value(|driver| self.drive_str(s, driver))
190 }
191
192 fn drive_str<'de>(
195 &self,
196 s: &'de str,
197 driver: &mut DeserializeDriver<'_, 'de>,
198 ) -> Result<(), Error> {
199 de::Deserializer::drive(
200 &mut Deserializer::from_str_with_config(s, self.clone()),
201 driver,
202 )
203 }
204
205 pub fn from_slice<'de, T: Deserialize<'de>>(&self, bytes: &'de [u8]) -> Result<T, Error> {
209 deserialize_value(|driver| self.drive_slice(bytes, driver))
210 }
211
212 fn drive_slice<'de>(
215 &self,
216 bytes: &'de [u8],
217 driver: &mut DeserializeDriver<'_, 'de>,
218 ) -> Result<(), Error> {
219 de::Deserializer::drive(
220 &mut Deserializer::from_slice_with_config(bytes, self.clone()),
221 driver,
222 )
223 }
224}
225
226#[derive(Debug, Clone)]
230#[must_use]
231pub struct DeserializerConfigBuilder {
232 value: DeserializerConfig,
233}
234
235impl DeserializerConfigBuilder {
236 pub const fn new() -> DeserializerConfigBuilder {
238 DeserializerConfigBuilder {
239 value: DeserializerConfig::new(),
240 }
241 }
242
243 pub const fn attribute_prefix(mut self, prefix: &'static str) -> DeserializerConfigBuilder {
247 self.value.set_attribute_prefix(prefix);
248 self
249 }
250
251 pub const fn text_key(mut self, key: &'static str) -> DeserializerConfigBuilder {
255 self.value.set_text_key(key);
256 self
257 }
258
259 pub const fn resolve_namespaces(mut self, yes: bool) -> DeserializerConfigBuilder {
263 self.value.set_resolve_namespaces(yes);
264 self
265 }
266
267 pub fn context(mut self, context: deser_core::Context) -> DeserializerConfigBuilder {
271 self.value.set_context(context);
272 self
273 }
274
275 pub const fn build(self) -> DeserializerConfig {
277 let value = unsafe { core::ptr::read(&self.value) };
281 core::mem::forget(self);
282 value
283 }
284}
285
286impl Default for DeserializerConfigBuilder {
287 fn default() -> DeserializerConfigBuilder {
288 DeserializerConfigBuilder::new()
289 }
290}
291
292pub fn from_str<'de, T: Deserialize<'de>>(s: &'de str) -> Result<T, Error> {
305 DeserializerConfig::new().from_str(s)
306}
307
308pub fn from_slice<'de, T: Deserialize<'de>>(bytes: &'de [u8]) -> Result<T, Error> {
310 DeserializerConfig::new().from_slice(bytes)
311}
312
313pub struct Deserializer<'a> {
315 input: &'a str,
316 error: Option<Error>,
317 config: DeserializerConfig,
318}
319
320impl<'a> Deserializer<'a> {
321 #[allow(clippy::should_implement_trait)]
323 pub fn from_str(input: &'a str) -> Deserializer<'a> {
324 Deserializer::from_str_with_config(input, DeserializerConfig::new())
325 }
326
327 pub fn from_str_with_config(input: &'a str, config: DeserializerConfig) -> Deserializer<'a> {
329 Deserializer {
330 input,
331 error: None,
332 config,
333 }
334 }
335
336 pub fn from_slice(input: &'a [u8]) -> Deserializer<'a> {
338 Deserializer::from_slice_with_config(input, DeserializerConfig::new())
339 }
340
341 pub fn from_slice_with_config(input: &'a [u8], config: DeserializerConfig) -> Deserializer<'a> {
344 let input = input.strip_prefix(b"\xef\xbb\xbf").unwrap_or(input);
346 match std::str::from_utf8(input) {
347 Ok(input) => Deserializer::from_str_with_config(input, config),
348 Err(err) => Deserializer {
349 input: "",
350 error: Some(Error::with_offset(
351 ErrorKind::Syntax,
352 "input is not valid UTF-8",
353 err.valid_up_to(),
354 )),
355 config,
356 },
357 }
358 }
359
360 pub fn config(&self) -> &DeserializerConfig {
362 &self.config
363 }
364
365 pub fn deserialize<T: Deserialize<'a>>(&mut self) -> Result<T, Error> {
367 de::Deserializer::deserialize(self)
368 }
369
370 pub fn deserialize_with<T, F>(&mut self, setup: F) -> Result<T, Error>
375 where
376 T: Deserialize<'a>,
377 F: FnOnce(&mut DeserializeDriver<'_, 'a>),
378 {
379 de::Deserializer::deserialize_with(self, setup)
380 }
381
382 pub fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
392 if !self.config.context.is_empty() {
393 driver.set_default_context(self.config.context.clone());
394 }
395 if let Some(err) = self.error.take() {
396 return Err(err);
397 }
398 let state = driver.state_mut();
399 if TrackLocations::of(state) {
400 Source(self.input.into()).set(state);
401 }
402 TEXT_RULES.set_default(state);
403 ContentKey(self.config.names.text_key).set(state);
406 *state.get_mut::<Names>() = self.config.names.clone();
407 Parser {
408 input: self.input,
409 config: &self.config,
410 reader: NsReader::from_str(self.input),
411 stack: Vec::new(),
412 root_done: false,
413 root: None,
414 declarations: None,
415 }
416 .run(driver)
417 .map_err(|mut err| {
418 err.resolve_position(self.input.as_bytes());
419 err
420 })
421 }
422}
423
424impl<'a> de::Deserializer<'a> for Deserializer<'a> {
425 fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
426 Deserializer::drive(self, driver)
427 }
428}
429
430const TEXT_RULES: LexicalRules = {
436 let mut rules = LexicalRules::STRICT;
437 rules.set_empty_is_null(true);
438 rules
439};
440
441type Range = (usize, usize);
443
444enum PendingText<'a> {
446 None,
447 Borrowed(&'a str, Range),
448 Owned(String, Range),
449}
450
451impl<'a> PendingText<'a> {
452 fn push(&mut self, text: Cow<'a, str>, range: Range) {
453 *self = match (std::mem::replace(self, PendingText::None), text) {
454 (PendingText::None, Cow::Borrowed(text)) => PendingText::Borrowed(text, range),
455 (PendingText::None, Cow::Owned(text)) => PendingText::Owned(text, range),
456 (PendingText::Borrowed(prev, (start, _)), text) => {
457 PendingText::Owned(prev.to_string() + &text, (start, range.1))
458 }
459 (PendingText::Owned(mut prev, (start, _)), text) => {
460 prev.push_str(&text);
461 PendingText::Owned(prev, (start, range.1))
462 }
463 };
464 }
465
466 fn is_blank(&self) -> bool {
467 match self {
468 PendingText::None => true,
469 PendingText::Borrowed(text, _) => is_blank(text),
470 PendingText::Owned(text, _) => is_blank(text),
471 }
472 }
473
474 fn emit(self, driver: &mut DeserializeDriver<'_, 'a>, fallback: Range) -> Result<(), Error> {
476 match self {
477 PendingText::None => emit_at(driver, Atom::Lexical(Text::borrowed("")), fallback),
478 PendingText::Borrowed(text, range) => {
479 driver.state_mut().set_input_range(range.0, range.1);
480 driver.emit_borrowed(Atom::Lexical(Text::borrowed(text)))
481 }
482 PendingText::Owned(text, range) => {
483 emit_at(driver, Atom::Lexical(Text::owned(text)), range)
484 }
485 }
486 }
487}
488
489fn is_blank(text: &str) -> bool {
490 text.bytes()
491 .all(|b| matches!(b, b' ' | b'\t' | b'\n' | b'\r'))
492}
493
494struct Element<'a> {
496 is_map: bool,
498 text: PendingText<'a>,
499 start: Range,
501}
502
503struct Parser<'a, 'c> {
504 input: &'a str,
505 config: &'c DeserializerConfig,
506 reader: NsReader<&'a [u8]>,
507 stack: Vec<Element<'a>>,
508 root_done: bool,
509 root: Option<RootData>,
512 declarations: Option<Vec<(String, String)>>,
515}
516
517impl<'a> Parser<'a, '_> {
518 fn run(mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
519 loop {
520 let start = self.position();
521 let event = self
522 .reader
523 .read_event()
524 .map_err(|err| xml_error(err, self.reader.error_position() as usize))?;
525 let range = (start, self.position());
526 match event {
527 XmlEvent::Start(ref tag) => self.start(driver, tag, range)?,
528 XmlEvent::Empty(ref tag) => {
529 self.start(driver, tag, range)?;
530 self.end(driver, range)?;
531 }
532 XmlEvent::End(_) => self.end(driver, range)?,
533 XmlEvent::Text(text) => {
534 self.text(text.xml_content(XmlVersion::Implicit1_0), range)?
535 }
536 XmlEvent::CData(text) => {
537 self.text(text.xml_content(XmlVersion::Implicit1_0), range)?
538 }
539 XmlEvent::GeneralRef(reference) => {
540 let text = resolve_reference(&reference, start)?;
541 self.text(Cow::Owned(text.to_string()), range)?
542 }
543 XmlEvent::Decl(_)
544 | XmlEvent::PI(_)
545 | XmlEvent::Comment(_)
546 | XmlEvent::DocType(_) => {}
547 XmlEvent::Eof => {
548 if !self.stack.is_empty() {
549 return Err(Error::with_offset(
550 ErrorKind::EndOfFile,
551 "unexpected end of input, an element is not closed",
552 start,
553 ));
554 }
555 if !self.root_done {
556 return Err(Error::with_offset(
557 ErrorKind::EndOfFile,
558 "no root element",
559 start,
560 ));
561 }
562 return Ok(());
563 }
564 }
565 }
566 }
567
568 fn position(&self) -> usize {
569 self.reader.buffer_position() as usize
570 }
571
572 fn make_map(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
574 if !self.stack.last().unwrap().is_map {
575 self.attach_element(driver);
576 let element = self.stack.last_mut().unwrap();
577 element.is_map = true;
578 emit_at(
579 driver,
580 Event::MapStart({
581 let mut shape = ContainerShape::with_order(Order::Significant);
582 shape.set_multimap(true);
583 shape
584 }),
585 element.start,
586 )?;
587 }
588 self.flush_text(driver)
589 }
590
591 fn flush_text(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
593 let element = self.stack.last_mut().unwrap();
594 if matches!(element.text, PendingText::None)
597 || (element.text.is_blank() && !WhitespaceDepths::applies(driver.state()))
598 {
599 element.text = PendingText::None;
600 return Ok(());
601 }
602 let text = std::mem::replace(&mut element.text, PendingText::None);
603 let range = match text {
604 PendingText::Borrowed(_, range) | PendingText::Owned(_, range) => range,
605 PendingText::None => unreachable!(),
606 };
607 emit_at(
608 driver,
609 Atom::Lexical(Text::borrowed(self.config.names.text_key)),
610 range,
611 )?;
612 text.emit(driver, range)
613 }
614
615 fn start(
616 &mut self,
617 driver: &mut DeserializeDriver<'_, 'a>,
618 tag: &BytesStart<'a>,
619 range: Range,
620 ) -> Result<(), Error> {
621 if self.stack.is_empty() {
622 if self.root_done {
623 return Err(Error::with_offset(
624 ErrorKind::Syntax,
625 "more than one root element",
626 range.0,
627 ));
628 }
629 self.root = Some(self.root_data(tag, range.0)?);
630 } else {
631 self.make_map(driver)?;
632 let name = self.name(tag.name(), false, range.0)?;
633 emit_key(driver, name, range)?;
634 if tag.attributes_raw().contains("xmlns") {
637 let declarations = self.declarations(tag, false, range.0)?;
638 if !declarations.is_empty() {
639 self.declarations = Some(declarations);
640 }
641 }
642 }
643 self.stack.push(Element {
644 is_map: false,
645 text: PendingText::None,
646 start: range,
647 });
648
649 for attr in tag.attributes() {
650 let attr = attr.map_err(|err| {
651 Error::with_offset(
652 ErrorKind::Syntax,
653 format!("invalid attribute: {err}"),
654 range.0,
655 )
656 })?;
657 let raw = attr.key.as_ref();
658 if raw == "xmlns" || raw.starts_with("xmlns:") {
660 continue;
661 }
662 self.make_map(driver)?;
663 let name = self.name(attr.key, true, range.0)?;
664 emit_key(driver, name, range)?;
665 let value = attr
666 .normalized_value(XmlVersion::Implicit1_0)
667 .map_err(|err| xml_error(err, range.0))?;
668 match reborrow(self.input, &value) {
669 Some(value) => {
670 driver.state_mut().set_input_range(range.0, range.1);
671 driver.emit_borrowed(Atom::Lexical(Text::borrowed(value)))?;
672 }
673 None => emit_at(driver, Atom::Lexical(Text::borrowed(&value)), range)?,
674 }
675 }
676 Ok(())
677 }
678
679 fn root_data(&self, tag: &BytesStart<'a>, offset: usize) -> Result<RootData, Error> {
685 Ok(RootData {
686 name: Some(self.name(tag.name(), false, offset)?.into_owned()),
687 namespaces: self.declarations(tag, true, offset)?,
688 })
689 }
690
691 fn declarations(
698 &self,
699 tag: &BytesStart<'a>,
700 is_root: bool,
701 offset: usize,
702 ) -> Result<Vec<(String, String)>, Error> {
703 let mut namespaces: Vec<(String, String)> = Vec::new();
704 for attr in tag.attributes().flatten() {
706 let raw: &str = attr.key.as_ref();
707 let prefix = match raw.strip_prefix("xmlns") {
708 Some("") => "",
709 Some(rest) => match rest.strip_prefix(':') {
710 Some(prefix) => prefix,
711 None => continue,
712 },
713 None => continue,
714 };
715 let uri = attr
716 .normalized_value(XmlVersion::Implicit1_0)
717 .map_err(|err| xml_error(err, offset))?;
718 if uri.is_empty() && (is_root || !prefix.is_empty()) {
719 continue;
720 }
721 let prefix = match self.config.names.namespaces.iter().find(|(_, x)| *x == uri) {
722 Some((alias, _)) => alias,
723 None => prefix,
724 };
725 if !namespaces.iter().any(|(x, _)| x == prefix) {
726 namespaces.push((prefix.to_string(), uri.into_owned()));
727 }
728 }
729 Ok(namespaces)
730 }
731
732 fn attach_element(&mut self, driver: &mut DeserializeDriver<'_, 'a>) {
739 if let Some(root) = self.root.take() {
740 *driver.state_mut().event_mut::<RootData>() = root;
741 }
742 if let Some(declarations) = self.declarations.take() {
743 driver.state_mut().event_mut::<Declarations>().0 = declarations;
744 }
745 }
746
747 fn end(&mut self, driver: &mut DeserializeDriver<'_, 'a>, range: Range) -> Result<(), Error> {
748 if self.stack.last().unwrap().is_map {
749 self.flush_text(driver)?;
750 self.stack.pop();
751 emit_at(driver, Event::MapEnd, range)?;
752 WhitespaceDepths::prune(driver.state_mut());
753 } else {
754 self.attach_element(driver);
755 let element = self.stack.pop().unwrap();
756 element.text.emit(driver, element.start)?;
757 }
758 if self.stack.is_empty() {
759 self.root_done = true;
760 }
761 Ok(())
762 }
763
764 fn text(&mut self, text: Cow<'a, str>, range: Range) -> Result<(), Error> {
765 match self.stack.last_mut() {
766 Some(element) => {
767 element.text.push(text, range);
768 Ok(())
769 }
770 None if is_blank(&text) => Ok(()),
771 None => Err(Error::with_offset(
772 ErrorKind::Syntax,
773 "text outside of the root element",
774 range.0,
775 )),
776 }
777 }
778
779 fn name(
781 &self,
782 name: QName<'_>,
783 is_attribute: bool,
784 offset: usize,
785 ) -> Result<Cow<'a, str>, Error> {
786 let names = &self.config.names;
787 let written: &str = name.as_ref();
788 let local_name = name.local_name();
789 let local: &str = local_name.as_ref();
790 let mut key = match self.namespace(name, is_attribute) {
791 Namespace::Alias("") => Cow::Owned(local.to_string()),
792 Namespace::Alias(alias) => Cow::Owned(format!("{alias}:{local}")),
793 Namespace::Uri(uri) => Cow::Owned(format!("{{{uri}}}{local}")),
794 Namespace::Unknown if self.config.resolve_namespaces => {
795 return Err(Error::with_offset(
796 ErrorKind::Syntax,
797 format!("the prefix of `{written}` is not declared"),
798 offset,
799 ));
800 }
801 Namespace::Written | Namespace::Unknown => match reborrow(self.input, written) {
802 Some(written) => Cow::Borrowed(written),
803 None => Cow::Owned(written.to_string()),
804 },
805 };
806 if is_attribute && !names.attribute_prefix.is_empty() {
807 key = Cow::Owned(format!("{}{}", names.attribute_prefix, key));
808 }
809 Ok(key)
810 }
811
812 fn namespace(&self, name: QName<'_>, is_attribute: bool) -> Namespace {
814 let namespaces = self.config.names.namespaces;
815 let resolve = self.config.resolve_namespaces;
816 if namespaces.is_empty() && !resolve {
817 return Namespace::Written;
818 }
819 let resolver = self.reader.resolver();
820 let (ns, _) = if is_attribute {
821 resolver.resolve_attribute(name)
822 } else {
823 resolver.resolve_element(name)
824 };
825 match ns {
826 ResolveResult::Bound(ns) => {
827 let uri: &str = ns.as_ref();
828 if let Some((alias, _)) = namespaces.iter().find(|(_, x)| *x == uri) {
829 Namespace::Alias(alias)
830 } else if !resolve {
831 Namespace::Written
832 } else if uri == XML_NAMESPACE {
833 Namespace::Alias("xml")
834 } else {
835 Namespace::Uri(uri.to_string())
836 }
837 }
838 ResolveResult::Unbound => Namespace::Written,
839 ResolveResult::Unknown(_) => Namespace::Unknown,
840 }
841 }
842}
843
844pub(crate) const XML_NAMESPACE: &str = "http://www.w3.org/XML/1998/namespace";
846
847enum Namespace {
849 Written,
851 Alias(&'static str),
853 Uri(String),
855 Unknown,
857}
858
859fn reborrow<'a>(input: &'a str, text: &str) -> Option<&'a str> {
861 let start = (text.as_ptr() as usize).checked_sub(input.as_ptr() as usize)?;
862 let end = start.checked_add(text.len())?;
863 input
864 .get(start..end)
865 .filter(|x| x.as_ptr() == text.as_ptr())
866}
867
868fn resolve_reference(reference: &BytesRef<'_>, offset: usize) -> Result<char, Error> {
873 if let Some(c) = reference
874 .resolve_char_ref()
875 .map_err(|err| xml_error(err, offset))?
876 {
877 return Ok(c);
878 }
879 match &*reference.xml_content(XmlVersion::Implicit1_0) {
880 "lt" => Ok('<'),
881 "gt" => Ok('>'),
882 "amp" => Ok('&'),
883 "apos" => Ok('\''),
884 "quot" => Ok('"'),
885 name => Err(Error::with_offset(
886 ErrorKind::Syntax,
887 format!("unknown entity `&{name};`"),
888 offset,
889 )),
890 }
891}
892
893fn xml_error(err: quick_xml::Error, offset: usize) -> Error {
894 Error::with_offset(ErrorKind::Syntax, format!("invalid XML: {err}"), offset)
895}
896
897fn emit_key<'a>(
898 driver: &mut DeserializeDriver<'_, 'a>,
899 key: Cow<'a, str>,
900 range: Range,
901) -> Result<(), Error> {
902 driver.state_mut().set_input_range(range.0, range.1);
903 match key {
904 Cow::Borrowed(key) => driver.emit_borrowed(Atom::Lexical(Text::borrowed(key))),
905 Cow::Owned(key) => driver.emit(Atom::Lexical(Text::owned(key))),
906 }
907}
908
909fn emit_at<'e, E: Into<Event<'e>>>(
910 driver: &mut DeserializeDriver<'_, '_>,
911 event: E,
912 range: Range,
913) -> Result<(), Error> {
914 driver.state_mut().set_input_range(range.0, range.1);
915 driver.emit(event)
916}