1 use std::io::Read;
2 
3 use serde::de;
4 use xml::reader::XmlEvent;
5 
6 use crate::de::ChildDeserializer;
7 use crate::debug_expect;
8 use crate::error::{Error, Result};
9 
10 pub struct SeqAccess<'a, R: Read> {
11     de: ChildDeserializer<'a, R>,
12     max_size: Option<usize>,
13     seq_type: SeqType,
14 }
15 
16 pub enum SeqType {
17     /// Sequence is of elements with the same name.
18     ByElementName {
19         expected_name: String,
20         search_non_contiguous: bool,
21     },
22     /// Sequence is of all elements/text at current depth.
23     AllMembers,
24 }
25 
26 impl<'a, R: 'a + Read> SeqAccess<'a, R> {
new(mut de: ChildDeserializer<'a, R>, max_size: Option<usize>) -> Self27     pub fn new(mut de: ChildDeserializer<'a, R>, max_size: Option<usize>) -> Self {
28         let seq_type = if de.unset_map_value() {
29             debug_expect!(de.peek(), Ok(&XmlEvent::StartElement { ref name, .. }) => {
30                 SeqType::ByElementName {
31                     expected_name: name.local_name.clone(),
32                     search_non_contiguous: de.non_contiguous_seq_elements
33                 }
34             })
35         } else {
36             SeqType::AllMembers
37         };
38         SeqAccess {
39             de,
40             max_size,
41             seq_type,
42         }
43     }
44 }
45 
46 impl<'de, 'a, R: 'a + Read> de::SeqAccess<'de> for SeqAccess<'a, R> {
47     type Error = Error;
48 
next_element_seed<T: de::DeserializeSeed<'de>>( &mut self, seed: T, ) -> Result<Option<T::Value>>49     fn next_element_seed<T: de::DeserializeSeed<'de>>(
50         &mut self,
51         seed: T,
52     ) -> Result<Option<T::Value>> {
53         match self.max_size.as_mut() {
54             Some(&mut 0) => {
55                 return Ok(None);
56             }
57             Some(max_size) => {
58                 *max_size -= 1;
59             }
60             None => {}
61         }
62 
63         match &self.seq_type {
64             SeqType::ByElementName {
65                 expected_name,
66                 search_non_contiguous,
67             } => {
68                 let mut local_depth = 0;
69 
70                 loop {
71                     let next_element = self.de.peek()?;
72 
73                     match next_element {
74                         XmlEvent::StartElement { name, .. }
75                             if &name.local_name == expected_name && local_depth == 0 =>
76                         {
77                             self.de.set_map_value();
78                             return seed.deserialize(&mut self.de).map(Some);
79                         }
80                         XmlEvent::StartElement { .. } => {
81                             if *search_non_contiguous {
82                                 self.de.buffered_reader.skip();
83                                 local_depth += 1;
84                             } else {
85                                 return Ok(None);
86                             }
87                         }
88                         XmlEvent::EndElement { .. } => {
89                             if local_depth == 0 {
90                                 return Ok(None);
91                             } else {
92                                 local_depth -= 1;
93                                 self.de.buffered_reader.skip();
94                             }
95                         }
96                         XmlEvent::EndDocument => {
97                             return Ok(None);
98                         }
99                         _ => {
100                             self.de.buffered_reader.skip();
101                         }
102                     }
103                 }
104             }
105             SeqType::AllMembers => {
106                 let next_element = self.de.peek()?;
107 
108                 match next_element {
109                     XmlEvent::EndElement { .. } | XmlEvent::EndDocument => return Ok(None),
110                     _ => {
111                         return seed.deserialize(&mut self.de).map(Some);
112                     }
113                 }
114             }
115         }
116     }
117 
size_hint(&self) -> Option<usize>118     fn size_hint(&self) -> Option<usize> {
119         self.max_size
120     }
121 }
122