serde_xml_rs/de/
map.rs

1use super::{
2    child::ChildDeserializer,
3    plain::PlainTextDeserializer,
4    reader::{Attribute, ChildReader, Event, Reader},
5};
6use crate::{
7    config::{CONTENT, TEXT},
8    error::{Error, Result},
9};
10use log::trace;
11use serde::de::IntoDeserializer;
12use std::{io::Read, iter::Peekable};
13
14pub struct MapAccess<'a, R: Read> {
15    reader: ChildReader<'a, R>,
16    attributes: Peekable<std::vec::IntoIter<Attribute>>,
17    fields: &'static [&'static str],
18}
19
20impl<'a, R: Read> MapAccess<'a, R> {
21    pub fn new_map(reader: ChildReader<'a, R>) -> Self {
22        Self {
23            reader,
24            attributes: vec![].into_iter().peekable(),
25            fields: &[],
26        }
27    }
28
29    pub fn new_struct(
30        reader: ChildReader<'a, R>,
31        attributes: Vec<Attribute>,
32        fields: &'static [&'static str],
33    ) -> Self {
34        Self {
35            reader,
36            attributes: attributes.into_iter().peekable(),
37            fields,
38        }
39    }
40
41    fn is_content(&self, element_name: &str) -> bool {
42        !self.fields.contains(&element_name) && self.fields.contains(&CONTENT)
43    }
44}
45
46impl<'de, R: Read> serde::de::MapAccess<'de> for MapAccess<'_, R> {
47    type Error = Error;
48
49    fn next_key_seed<K>(&mut self, seed: K) -> Result<Option<K::Value>>
50    where
51        K: serde::de::DeserializeSeed<'de>,
52    {
53        trace!("next map/struct key");
54        if let Some(attr) = self.attributes.peek() {
55            trace!("attribute {}", attr.qname());
56            seed.deserialize(format!("@{}", attr.qname()).into_deserializer())
57                .map(Some)
58        } else {
59            match self.reader.peek()? {
60                Event::StartElement(element) => {
61                    let element_name = element.qname();
62                    if self.is_content(&element_name) {
63                        trace!("#content");
64                        seed.deserialize(CONTENT.into_deserializer()).map(Some)
65                    } else {
66                        trace!("element '{}'", element_name);
67                        seed.deserialize(element_name.as_str().into_deserializer())
68                            .map(Some)
69                    }
70                }
71                Event::Text(_) => {
72                    trace!("{}", TEXT);
73                    seed.deserialize(TEXT.into_deserializer()).map(Some)
74                }
75                _ => Ok(None),
76            }
77        }
78    }
79
80    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value>
81    where
82        V: serde::de::DeserializeSeed<'de>,
83    {
84        if let Some(attr) = self.attributes.next() {
85            seed.deserialize(PlainTextDeserializer::new(&attr.value))
86        } else {
87            match self.reader.peek()? {
88                Event::StartElement(element) => {
89                    let element_name = element.qname();
90                    if self.is_content(&element_name) {
91                        seed.deserialize(ChildDeserializer::new(self.reader.child()))
92                    } else {
93                        seed.deserialize(ChildDeserializer::new_with_element_name(
94                            self.reader.child(),
95                            element_name,
96                        ))
97                    }
98                }
99                Event::Text(_) => {
100                    seed.deserialize(PlainTextDeserializer::new(&self.reader.chars()?))
101                }
102                event => Err(Error::Unexpected {
103                    expected: "start of element or text",
104                    but_got: event.to_string(),
105                }),
106            }
107        }
108    }
109}