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 fn context(&self) -> &deser_core::Context {
70 &self.context
71 }
72
73 pub const fn set_attribute_prefix(&mut self, prefix: &'static str) {
77 self.names.attribute_prefix = prefix;
78 }
79
80 pub const fn set_text_key(&mut self, key: &'static str) {
85 self.names.text_key = key;
86 }
87
88 pub const fn namespaces(
123 mut self,
124 namespaces: &'static [(&'static str, &'static str)],
125 ) -> DeserializerConfig {
126 self.names.namespaces = namespaces;
127 self
128 }
129
130 pub const fn set_resolve_namespaces(&mut self, yes: bool) {
176 self.resolve_namespaces = yes;
177 }
178
179 pub fn from_str<'de, T: Deserialize<'de>>(&self, s: &'de str) -> Result<T, Error> {
181 deserialize_value(|driver| self.drive_str(s, driver))
182 }
183
184 fn drive_str<'de>(
187 &self,
188 s: &'de str,
189 driver: &mut DeserializeDriver<'_, 'de>,
190 ) -> Result<(), Error> {
191 de::Deserializer::drive(
192 &mut Deserializer::from_str_with_config(s, self.clone()),
193 driver,
194 )
195 }
196
197 pub fn from_slice<'de, T: Deserialize<'de>>(&self, bytes: &'de [u8]) -> Result<T, Error> {
201 deserialize_value(|driver| self.drive_slice(bytes, driver))
202 }
203
204 fn drive_slice<'de>(
207 &self,
208 bytes: &'de [u8],
209 driver: &mut DeserializeDriver<'_, 'de>,
210 ) -> Result<(), Error> {
211 de::Deserializer::drive(
212 &mut Deserializer::from_slice_with_config(bytes, self.clone()),
213 driver,
214 )
215 }
216}
217
218#[derive(Debug, Clone)]
222#[must_use]
223pub struct DeserializerConfigBuilder {
224 value: DeserializerConfig,
225}
226
227impl DeserializerConfigBuilder {
228 pub const fn new() -> DeserializerConfigBuilder {
230 DeserializerConfigBuilder {
231 value: DeserializerConfig::new(),
232 }
233 }
234
235 pub const fn attribute_prefix(mut self, prefix: &'static str) -> DeserializerConfigBuilder {
239 self.value.set_attribute_prefix(prefix);
240 self
241 }
242
243 pub const fn text_key(mut self, key: &'static str) -> DeserializerConfigBuilder {
247 self.value.set_text_key(key);
248 self
249 }
250
251 pub const fn resolve_namespaces(mut self, yes: bool) -> DeserializerConfigBuilder {
255 self.value.set_resolve_namespaces(yes);
256 self
257 }
258
259 pub fn context(mut self, context: deser_core::Context) -> DeserializerConfigBuilder {
263 self.value.set_context(context);
264 self
265 }
266
267 pub const fn build(self) -> DeserializerConfig {
269 let value = unsafe { core::ptr::read(&self.value) };
273 core::mem::forget(self);
274 value
275 }
276}
277
278impl Default for DeserializerConfigBuilder {
279 fn default() -> DeserializerConfigBuilder {
280 DeserializerConfigBuilder::new()
281 }
282}
283
284pub fn from_str<'de, T: Deserialize<'de>>(s: &'de str) -> Result<T, Error> {
297 DeserializerConfig::new().from_str(s)
298}
299
300pub fn from_slice<'de, T: Deserialize<'de>>(bytes: &'de [u8]) -> Result<T, Error> {
302 DeserializerConfig::new().from_slice(bytes)
303}
304
305pub struct Deserializer<'a> {
307 input: &'a str,
308 error: Option<Error>,
309 config: DeserializerConfig,
310}
311
312impl<'a> Deserializer<'a> {
313 #[allow(clippy::should_implement_trait)]
315 pub fn from_str(input: &'a str) -> Deserializer<'a> {
316 Deserializer::from_str_with_config(input, DeserializerConfig::new())
317 }
318
319 pub fn from_str_with_config(input: &'a str, config: DeserializerConfig) -> Deserializer<'a> {
321 Deserializer {
322 input,
323 error: None,
324 config,
325 }
326 }
327
328 pub fn from_slice(input: &'a [u8]) -> Deserializer<'a> {
330 Deserializer::from_slice_with_config(input, DeserializerConfig::new())
331 }
332
333 pub fn from_slice_with_config(input: &'a [u8], config: DeserializerConfig) -> Deserializer<'a> {
336 let input = input.strip_prefix(b"\xef\xbb\xbf").unwrap_or(input);
338 match std::str::from_utf8(input) {
339 Ok(input) => Deserializer::from_str_with_config(input, config),
340 Err(err) => Deserializer {
341 input: "",
342 error: Some(Error::with_offset(
343 ErrorKind::Syntax,
344 "input is not valid UTF-8",
345 err.valid_up_to(),
346 )),
347 config,
348 },
349 }
350 }
351
352 pub fn config(&self) -> &DeserializerConfig {
354 &self.config
355 }
356
357 pub fn deserialize<T: Deserialize<'a>>(&mut self) -> Result<T, Error> {
359 de::Deserializer::deserialize(self)
360 }
361
362 pub fn deserialize_with<T, F>(&mut self, setup: F) -> Result<T, Error>
367 where
368 T: Deserialize<'a>,
369 F: FnOnce(&mut DeserializeDriver<'_, 'a>),
370 {
371 de::Deserializer::deserialize_with(self, setup)
372 }
373
374 pub fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
380 if let Some(err) = self.error.take() {
381 return Err(err);
382 }
383 let state = driver.state_mut();
384 if TrackLocations::of(state) {
385 Source(self.input.into()).set(state);
386 }
387 TEXT_RULES.set_default(state);
388 ContentKey(self.config.names.text_key).set(state);
391 *state.get_mut::<Names>() = self.config.names.clone();
392 Parser {
393 input: self.input,
394 config: &self.config,
395 reader: NsReader::from_str(self.input),
396 stack: Vec::new(),
397 root_done: false,
398 root: None,
399 declarations: None,
400 }
401 .run(driver)
402 .map_err(|mut err| {
403 err.resolve_position(self.input.as_bytes());
404 err
405 })
406 }
407}
408
409impl<'a> de::Deserializer<'a> for Deserializer<'a> {
410 fn drive(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
411 if !self.config.context.is_empty() {
412 driver.set_default_context(self.config.context.clone());
413 }
414 Deserializer::drive(self, driver)
415 }
416}
417
418const TEXT_RULES: LexicalRules = {
424 let mut rules = LexicalRules::STRICT;
425 rules.set_empty_is_null(true);
426 rules
427};
428
429type Range = (usize, usize);
431
432enum PendingText<'a> {
434 None,
435 Borrowed(&'a str, Range),
436 Owned(String, Range),
437}
438
439impl<'a> PendingText<'a> {
440 fn push(&mut self, text: Cow<'a, str>, range: Range) {
441 *self = match (std::mem::replace(self, PendingText::None), text) {
442 (PendingText::None, Cow::Borrowed(text)) => PendingText::Borrowed(text, range),
443 (PendingText::None, Cow::Owned(text)) => PendingText::Owned(text, range),
444 (PendingText::Borrowed(prev, (start, _)), text) => {
445 PendingText::Owned(prev.to_string() + &text, (start, range.1))
446 }
447 (PendingText::Owned(mut prev, (start, _)), text) => {
448 prev.push_str(&text);
449 PendingText::Owned(prev, (start, range.1))
450 }
451 };
452 }
453
454 fn is_blank(&self) -> bool {
455 match self {
456 PendingText::None => true,
457 PendingText::Borrowed(text, _) => is_blank(text),
458 PendingText::Owned(text, _) => is_blank(text),
459 }
460 }
461
462 fn emit(self, driver: &mut DeserializeDriver<'_, 'a>, fallback: Range) -> Result<(), Error> {
464 match self {
465 PendingText::None => emit_at(driver, Atom::Lexical(Text::borrowed("")), fallback),
466 PendingText::Borrowed(text, range) => {
467 driver.state_mut().set_input_range(range.0, range.1);
468 driver.emit_borrowed(Atom::Lexical(Text::borrowed(text)))
469 }
470 PendingText::Owned(text, range) => {
471 emit_at(driver, Atom::Lexical(Text::owned(text)), range)
472 }
473 }
474 }
475}
476
477fn is_blank(text: &str) -> bool {
478 text.bytes()
479 .all(|b| matches!(b, b' ' | b'\t' | b'\n' | b'\r'))
480}
481
482struct Element<'a> {
484 is_map: bool,
486 text: PendingText<'a>,
487 start: Range,
489}
490
491struct Parser<'a, 'c> {
492 input: &'a str,
493 config: &'c DeserializerConfig,
494 reader: NsReader<&'a [u8]>,
495 stack: Vec<Element<'a>>,
496 root_done: bool,
497 root: Option<RootData>,
500 declarations: Option<Vec<(String, String)>>,
503}
504
505impl<'a> Parser<'a, '_> {
506 fn run(mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
507 loop {
508 let start = self.position();
509 let event = self
510 .reader
511 .read_event()
512 .map_err(|err| xml_error(err, self.reader.error_position() as usize))?;
513 let range = (start, self.position());
514 match event {
515 XmlEvent::Start(ref tag) => self.start(driver, tag, range)?,
516 XmlEvent::Empty(ref tag) => {
517 self.start(driver, tag, range)?;
518 self.end(driver, range)?;
519 }
520 XmlEvent::End(_) => self.end(driver, range)?,
521 XmlEvent::Text(text) => {
522 self.text(text.xml_content(XmlVersion::Implicit1_0), range)?
523 }
524 XmlEvent::CData(text) => {
525 self.text(text.xml_content(XmlVersion::Implicit1_0), range)?
526 }
527 XmlEvent::GeneralRef(reference) => {
528 let text = resolve_reference(&reference, start)?;
529 self.text(Cow::Owned(text.to_string()), range)?
530 }
531 XmlEvent::Decl(_)
532 | XmlEvent::PI(_)
533 | XmlEvent::Comment(_)
534 | XmlEvent::DocType(_) => {}
535 XmlEvent::Eof => {
536 if !self.stack.is_empty() {
537 return Err(Error::with_offset(
538 ErrorKind::EndOfFile,
539 "unexpected end of input, an element is not closed",
540 start,
541 ));
542 }
543 if !self.root_done {
544 return Err(Error::with_offset(
545 ErrorKind::EndOfFile,
546 "no root element",
547 start,
548 ));
549 }
550 return Ok(());
551 }
552 }
553 }
554 }
555
556 fn position(&self) -> usize {
557 self.reader.buffer_position() as usize
558 }
559
560 fn make_map(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
562 if !self.stack.last().unwrap().is_map {
563 self.attach_element(driver);
564 let element = self.stack.last_mut().unwrap();
565 element.is_map = true;
566 emit_at(
567 driver,
568 Event::MapStart({
569 let mut shape = ContainerShape::with_order(Order::Significant);
570 shape.set_multimap(true);
571 shape
572 }),
573 element.start,
574 )?;
575 }
576 self.flush_text(driver)
577 }
578
579 fn flush_text(&mut self, driver: &mut DeserializeDriver<'_, 'a>) -> Result<(), Error> {
581 let element = self.stack.last_mut().unwrap();
582 if matches!(element.text, PendingText::None)
585 || (element.text.is_blank() && !WhitespaceDepths::applies(driver.state()))
586 {
587 element.text = PendingText::None;
588 return Ok(());
589 }
590 let text = std::mem::replace(&mut element.text, PendingText::None);
591 let range = match text {
592 PendingText::Borrowed(_, range) | PendingText::Owned(_, range) => range,
593 PendingText::None => unreachable!(),
594 };
595 emit_at(
596 driver,
597 Atom::Lexical(Text::borrowed(self.config.names.text_key)),
598 range,
599 )?;
600 text.emit(driver, range)
601 }
602
603 fn start(
604 &mut self,
605 driver: &mut DeserializeDriver<'_, 'a>,
606 tag: &BytesStart<'a>,
607 range: Range,
608 ) -> Result<(), Error> {
609 if self.stack.is_empty() {
610 if self.root_done {
611 return Err(Error::with_offset(
612 ErrorKind::Syntax,
613 "more than one root element",
614 range.0,
615 ));
616 }
617 self.root = Some(self.root_data(tag, range.0)?);
618 } else {
619 self.make_map(driver)?;
620 let name = self.name(tag.name(), false, range.0)?;
621 emit_key(driver, name, range)?;
622 if tag.attributes_raw().contains("xmlns") {
625 let declarations = self.declarations(tag, false, range.0)?;
626 if !declarations.is_empty() {
627 self.declarations = Some(declarations);
628 }
629 }
630 }
631 self.stack.push(Element {
632 is_map: false,
633 text: PendingText::None,
634 start: range,
635 });
636
637 for attr in tag.attributes() {
638 let attr = attr.map_err(|err| {
639 Error::with_offset(
640 ErrorKind::Syntax,
641 format!("invalid attribute: {err}"),
642 range.0,
643 )
644 })?;
645 let raw = attr.key.as_ref();
646 if raw == "xmlns" || raw.starts_with("xmlns:") {
648 continue;
649 }
650 self.make_map(driver)?;
651 let name = self.name(attr.key, true, range.0)?;
652 emit_key(driver, name, range)?;
653 let value = attr
654 .normalized_value(XmlVersion::Implicit1_0)
655 .map_err(|err| xml_error(err, range.0))?;
656 match reborrow(self.input, &value) {
657 Some(value) => {
658 driver.state_mut().set_input_range(range.0, range.1);
659 driver.emit_borrowed(Atom::Lexical(Text::borrowed(value)))?;
660 }
661 None => emit_at(driver, Atom::Lexical(Text::borrowed(&value)), range)?,
662 }
663 }
664 Ok(())
665 }
666
667 fn root_data(&self, tag: &BytesStart<'a>, offset: usize) -> Result<RootData, Error> {
673 Ok(RootData {
674 name: Some(self.name(tag.name(), false, offset)?.into_owned()),
675 namespaces: self.declarations(tag, true, offset)?,
676 })
677 }
678
679 fn declarations(
686 &self,
687 tag: &BytesStart<'a>,
688 is_root: bool,
689 offset: usize,
690 ) -> Result<Vec<(String, String)>, Error> {
691 let mut namespaces: Vec<(String, String)> = Vec::new();
692 for attr in tag.attributes().flatten() {
694 let raw: &str = attr.key.as_ref();
695 let prefix = match raw.strip_prefix("xmlns") {
696 Some("") => "",
697 Some(rest) => match rest.strip_prefix(':') {
698 Some(prefix) => prefix,
699 None => continue,
700 },
701 None => continue,
702 };
703 let uri = attr
704 .normalized_value(XmlVersion::Implicit1_0)
705 .map_err(|err| xml_error(err, offset))?;
706 if uri.is_empty() && (is_root || !prefix.is_empty()) {
707 continue;
708 }
709 let prefix = match self.config.names.namespaces.iter().find(|(_, x)| *x == uri) {
710 Some((alias, _)) => alias,
711 None => prefix,
712 };
713 if !namespaces.iter().any(|(x, _)| x == prefix) {
714 namespaces.push((prefix.to_string(), uri.into_owned()));
715 }
716 }
717 Ok(namespaces)
718 }
719
720 fn attach_element(&mut self, driver: &mut DeserializeDriver<'_, 'a>) {
727 if let Some(root) = self.root.take() {
728 *driver.state_mut().event_mut::<RootData>() = root;
729 }
730 if let Some(declarations) = self.declarations.take() {
731 driver.state_mut().event_mut::<Declarations>().0 = declarations;
732 }
733 }
734
735 fn end(&mut self, driver: &mut DeserializeDriver<'_, 'a>, range: Range) -> Result<(), Error> {
736 if self.stack.last().unwrap().is_map {
737 self.flush_text(driver)?;
738 self.stack.pop();
739 emit_at(driver, Event::MapEnd, range)?;
740 WhitespaceDepths::prune(driver.state_mut());
741 } else {
742 self.attach_element(driver);
743 let element = self.stack.pop().unwrap();
744 element.text.emit(driver, element.start)?;
745 }
746 if self.stack.is_empty() {
747 self.root_done = true;
748 }
749 Ok(())
750 }
751
752 fn text(&mut self, text: Cow<'a, str>, range: Range) -> Result<(), Error> {
753 match self.stack.last_mut() {
754 Some(element) => {
755 element.text.push(text, range);
756 Ok(())
757 }
758 None if is_blank(&text) => Ok(()),
759 None => Err(Error::with_offset(
760 ErrorKind::Syntax,
761 "text outside of the root element",
762 range.0,
763 )),
764 }
765 }
766
767 fn name(
769 &self,
770 name: QName<'_>,
771 is_attribute: bool,
772 offset: usize,
773 ) -> Result<Cow<'a, str>, Error> {
774 let names = &self.config.names;
775 let written: &str = name.as_ref();
776 let local_name = name.local_name();
777 let local: &str = local_name.as_ref();
778 let mut key = match self.namespace(name, is_attribute) {
779 Namespace::Alias("") => Cow::Owned(local.to_string()),
780 Namespace::Alias(alias) => Cow::Owned(format!("{alias}:{local}")),
781 Namespace::Uri(uri) => Cow::Owned(format!("{{{uri}}}{local}")),
782 Namespace::Unknown if self.config.resolve_namespaces => {
783 return Err(Error::with_offset(
784 ErrorKind::Syntax,
785 format!("the prefix of `{written}` is not declared"),
786 offset,
787 ));
788 }
789 Namespace::Written | Namespace::Unknown => match reborrow(self.input, written) {
790 Some(written) => Cow::Borrowed(written),
791 None => Cow::Owned(written.to_string()),
792 },
793 };
794 if is_attribute && !names.attribute_prefix.is_empty() {
795 key = Cow::Owned(format!("{}{}", names.attribute_prefix, key));
796 }
797 Ok(key)
798 }
799
800 fn namespace(&self, name: QName<'_>, is_attribute: bool) -> Namespace {
802 let namespaces = self.config.names.namespaces;
803 let resolve = self.config.resolve_namespaces;
804 if namespaces.is_empty() && !resolve {
805 return Namespace::Written;
806 }
807 let resolver = self.reader.resolver();
808 let (ns, _) = if is_attribute {
809 resolver.resolve_attribute(name)
810 } else {
811 resolver.resolve_element(name)
812 };
813 match ns {
814 ResolveResult::Bound(ns) => {
815 let uri: &str = ns.as_ref();
816 if let Some((alias, _)) = namespaces.iter().find(|(_, x)| *x == uri) {
817 Namespace::Alias(alias)
818 } else if !resolve {
819 Namespace::Written
820 } else if uri == XML_NAMESPACE {
821 Namespace::Alias("xml")
822 } else {
823 Namespace::Uri(uri.to_string())
824 }
825 }
826 ResolveResult::Unbound => Namespace::Written,
827 ResolveResult::Unknown(_) => Namespace::Unknown,
828 }
829 }
830}
831
832pub(crate) const XML_NAMESPACE: &str = "http://www.w3.org/XML/1998/namespace";
834
835enum Namespace {
837 Written,
839 Alias(&'static str),
841 Uri(String),
843 Unknown,
845}
846
847fn reborrow<'a>(input: &'a str, text: &str) -> Option<&'a str> {
849 let start = (text.as_ptr() as usize).checked_sub(input.as_ptr() as usize)?;
850 let end = start.checked_add(text.len())?;
851 input
852 .get(start..end)
853 .filter(|x| x.as_ptr() == text.as_ptr())
854}
855
856fn resolve_reference(reference: &BytesRef<'_>, offset: usize) -> Result<char, Error> {
861 if let Some(c) = reference
862 .resolve_char_ref()
863 .map_err(|err| xml_error(err, offset))?
864 {
865 return Ok(c);
866 }
867 match &*reference.xml_content(XmlVersion::Implicit1_0) {
868 "lt" => Ok('<'),
869 "gt" => Ok('>'),
870 "amp" => Ok('&'),
871 "apos" => Ok('\''),
872 "quot" => Ok('"'),
873 name => Err(Error::with_offset(
874 ErrorKind::Syntax,
875 format!("unknown entity `&{name};`"),
876 offset,
877 )),
878 }
879}
880
881fn xml_error(err: quick_xml::Error, offset: usize) -> Error {
882 Error::with_offset(ErrorKind::Syntax, format!("invalid XML: {err}"), offset)
883}
884
885fn emit_key<'a>(
886 driver: &mut DeserializeDriver<'_, 'a>,
887 key: Cow<'a, str>,
888 range: Range,
889) -> Result<(), Error> {
890 driver.state_mut().set_input_range(range.0, range.1);
891 match key {
892 Cow::Borrowed(key) => driver.emit_borrowed(Atom::Lexical(Text::borrowed(key))),
893 Cow::Owned(key) => driver.emit(Atom::Lexical(Text::owned(key))),
894 }
895}
896
897fn emit_at<'e, E: Into<Event<'e>>>(
898 driver: &mut DeserializeDriver<'_, '_>,
899 event: E,
900 range: Range,
901) -> Result<(), Error> {
902 driver.state_mut().set_input_range(range.0, range.1);
903 driver.emit(event)
904}