sgmlish/de/
mod.rs

1//! Deserialize SGML data to a Rust data structure.
2
3use std::borrow::Cow;
4use std::rc::Rc;
5use std::{fmt, mem};
6
7use log::{debug, trace};
8use serde::de::{self, IntoDeserializer, Unexpected};
9use serde::Deserializer;
10
11use crate::de::buffer::CowBuffer;
12use crate::{SgmlEvent, SgmlFragment};
13
14mod buffer;
15
16/// Deserializes an instance of type `T` from the given [`SgmlFragment`].
17///
18/// Before invoking, make sure the content is *tag-valid* and consistently cased.
19/// That means all start tags must have a matching end tag with identical case,
20/// in a consistent hierarchy.
21///
22/// # Example
23///
24/// ```rust
25/// use serde::Deserialize;
26///
27/// #[derive(Debug, Deserialize)]
28/// struct Select {
29///     name: Option<String>,
30///     #[serde(rename = "option")]
31///     options: Vec<SelectOption>,
32/// }
33///
34/// #[derive(Debug, Deserialize)]
35/// struct SelectOption {
36///     #[serde(rename = "$value")]
37///     label: String,
38///     value: Option<String>,
39///     #[serde(default)]
40///     selected: bool,
41/// }
42///
43/// # fn main() -> sgmlish::Result<()> {
44/// let sgml = r##"
45///     <SELECT NAME="color">
46///         <OPTION VALUE="">Choose one
47///         <OPTION SELECTED>Red
48///         <OPTION>Green
49///         <OPTION>Blue
50///     </SELECT>
51/// "##;
52/// let sgml = sgmlish::Parser::builder()
53///     .lowercase_names()
54///     .parse(sgml)?;
55/// let sgml = sgmlish::transforms::normalize_end_tags(sgml)?;
56/// let select = sgmlish::from_fragment::<Select>(sgml)?;
57///
58/// println!("Deserialized:\n{:#?}", select);
59///
60/// assert_eq!(select.name.as_deref(), Some("color"));
61/// assert_eq!(select.options.len(), 4);
62/// assert_eq!(select.options[0].label, "Choose one");
63/// assert!(!select.options[0].selected);
64/// assert_eq!(select.options[1].label, "Red");
65/// assert!(select.options[1].selected);
66/// # Ok(())
67/// # }
68/// ```
69pub fn from_fragment<'de, T>(fragment: SgmlFragment<'de>) -> Result<T, DeserializationError>
70where
71    T: de::Deserialize<'de>,
72{
73    let mut reader = SgmlDeserializer::from_fragment(fragment)?;
74    T::deserialize(&mut reader)
75}
76
77/// A deserializer for SGML content.
78#[derive(Debug)]
79pub struct SgmlDeserializer<'de> {
80    events: std::vec::IntoIter<SgmlEvent<'de>>,
81    stack: Vec<Cow<'de, str>>,
82    map_key: Option<Rc<str>>,
83    accumulated_text: Option<Cow<'de, str>>,
84}
85
86/// The error type for deserialization problems.
87#[derive(Debug, thiserror::Error)]
88pub enum DeserializationError {
89    #[error("unexpected end of content")]
90    UnexpectedEof,
91    #[error("empty stack")]
92    EmptyStack,
93    #[error("expected start tag")]
94    ExpectedStartTag,
95    #[error("mismatched close tag: expected </{expected}>, found </{found}>")]
96    MismatchedCloseTag { expected: String, found: String },
97    /// An event which is not supported by deserialization was found.
98    #[error("deserialization of '{0}' is not supported")]
99    Unsupported(SgmlEvent<'static>),
100
101    #[error("error parsing integer value: {source}")]
102    ParseIntError {
103        #[from]
104        source: std::num::ParseIntError,
105    },
106    #[error("error parsing float value: {source}")]
107    ParseFloatError {
108        #[from]
109        source: std::num::ParseFloatError,
110    },
111
112    #[error("{0}")]
113    Message(String),
114}
115
116impl<'de> SgmlDeserializer<'de> {
117    pub fn from_fragment(fragment: SgmlFragment<'de>) -> Result<Self, DeserializationError> {
118        let mut reader = SgmlDeserializer {
119            events: fragment.into_vec().into_iter(),
120            stack: Vec::new(),
121            map_key: None,
122            accumulated_text: None,
123        };
124        reader.normalize_at_cursor()?;
125        Ok(reader)
126    }
127
128    fn advance(&mut self) -> Result<SgmlEvent<'de>, DeserializationError> {
129        if let Some(next) = self.events.next() {
130            self.normalize_at_cursor()?;
131            Ok(next)
132        } else {
133            Err(DeserializationError::UnexpectedEof)
134        }
135    }
136
137    fn peek(&self) -> Result<&SgmlEvent<'de>, DeserializationError> {
138        let current = self
139            .events
140            .as_slice()
141            .get(0)
142            .ok_or(DeserializationError::UnexpectedEof)?;
143        trace!("peeked: {:?}", current);
144        Ok(current)
145    }
146
147    fn peek_mut(&mut self) -> Result<&mut SgmlEvent<'de>, DeserializationError> {
148        let current = self
149            .events
150            .as_mut_slice()
151            .get_mut(0)
152            .ok_or(DeserializationError::UnexpectedEof)?;
153        trace!("peeked: {:?}", current);
154        Ok(current)
155    }
156
157    fn peek_content_type(&self) -> Result<PeekContentType, DeserializationError> {
158        let mut contains_text = false;
159        let contains_child_elements = self
160            .events
161            .as_slice()
162            .iter()
163            .skip(1)
164            .find_map(|event| match event {
165                SgmlEvent::OpenStartTag { .. } => Some(true),
166                SgmlEvent::EndTag { .. } => Some(false),
167                SgmlEvent::Character(text) if !text.is_empty() => {
168                    contains_text = true;
169                    None
170                }
171                _ => None,
172            })
173            .ok_or(DeserializationError::UnexpectedEof)?;
174
175        let content = PeekContentType {
176            contains_child_elements,
177            contains_text,
178        };
179        trace!("peeked content type: {:?}", content);
180        Ok(content)
181    }
182
183    /// Rejects unsupported events (like empty start tags), ignores markup declarations and processing instructions,
184    /// and ensures any `Data` is expanded
185    fn normalize_at_cursor(&mut self) -> Result<(), DeserializationError> {
186        let event = match self.events.as_mut_slice().get_mut(0) {
187            Some(event) => event,
188            None => return Ok(()),
189        };
190        match event {
191            SgmlEvent::MarkupDeclaration { .. }
192            | SgmlEvent::ProcessingInstruction(_)
193            | SgmlEvent::MarkedSection { .. } => {}
194            SgmlEvent::OpenStartTag { name } | SgmlEvent::EndTag { name } if name.is_empty() => {}
195            _ => return Ok(()),
196        }
197        Err(DeserializationError::Unsupported(
198            self.events.next().unwrap().into_owned(),
199        ))
200    }
201
202    fn expect_start_tag(&self) -> Result<&Cow<'de, str>, DeserializationError> {
203        match self.peek() {
204            Ok(SgmlEvent::OpenStartTag { name }) => Ok(name),
205            _ => Err(DeserializationError::ExpectedStartTag),
206        }
207    }
208
209    /// Consumes the current event, asserting it is an open tag, and pushes it to the stack.
210    fn push_elt(&mut self) -> Result<&str, DeserializationError> {
211        let stag = match self.events.next() {
212            Some(SgmlEvent::OpenStartTag { name }) => name,
213            _ => return Err(DeserializationError::ExpectedStartTag),
214        };
215        debug!("push({}): {:?}", self.stack.len(), stag);
216        self.stack.push(stag);
217        self.normalize_at_cursor()?;
218        Ok(self.stack.last().unwrap())
219    }
220
221    /// Consumes all events until the current top of the stack is popped.
222    fn pop_elt(&mut self) -> Result<(), DeserializationError> {
223        let stack_size = self.stack.len();
224        trace!(
225            "popping({}): {:?}",
226            stack_size - 1,
227            &self.stack[stack_size - 1]
228        );
229        loop {
230            match self
231                .events
232                .next()
233                .ok_or(DeserializationError::UnexpectedEof)?
234            {
235                SgmlEvent::XmlCloseEmptyElement => {
236                    self.stack.pop();
237                    return Ok(());
238                }
239                SgmlEvent::EndTag { name } => {
240                    self.check_stack_size(stack_size);
241                    let expected = self.stack.pop().unwrap();
242                    if name != expected {
243                        return Err(DeserializationError::MismatchedCloseTag {
244                            expected: expected.to_string(),
245                            found: name.to_string(),
246                        });
247                    }
248                    debug!("popped({}): {:?}", stack_size, name);
249                    return Ok(());
250                }
251                SgmlEvent::OpenStartTag { name } => {
252                    self.stack.push(name);
253                    self.pop_elt()?;
254                }
255                _ => {}
256            };
257        }
258    }
259
260    /// Skips attributes and CloseStartTag, going to the main content.
261    ///
262    /// Should only be used immediately after `push_elt`.
263    fn advance_to_content(&mut self) -> Result<(), DeserializationError> {
264        while let SgmlEvent::Attribute { .. } | SgmlEvent::CloseStartTag = self.peek()? {
265            self.advance()?;
266        }
267        Ok(())
268    }
269
270    /// Consumes an element and returns all its text.
271    ///
272    /// Includes text from child elements as well.
273    fn consume_text<'r, V: de::Visitor<'r>>(
274        &mut self,
275    ) -> Result<Cow<'de, str>, DeserializationError> {
276        if let Some(accumulated_text) = self.accumulated_text.take() {
277            debug!("consume_text accumulated");
278            return Ok(accumulated_text);
279        }
280
281        debug!("consume_text");
282        if let SgmlEvent::Attribute { name, value } = self.peek_mut()? {
283            let value = mem::take(value);
284            debug!("consumed text from attribute({}): {:?}", name, value);
285            self.advance()?;
286            return Ok(value.unwrap_or_default());
287        }
288
289        let starting_stack_size = self.stack.len();
290        self.push_elt()?;
291
292        let mut text = CowBuffer::new();
293
294        loop {
295            match self.peek_mut()? {
296                SgmlEvent::OpenStartTag { .. } => {
297                    self.push_elt()?;
298                }
299                SgmlEvent::EndTag { .. } => {
300                    self.pop_elt()?;
301                    if self.stack.len() == starting_stack_size {
302                        break;
303                    }
304                }
305                SgmlEvent::Character(t) => {
306                    text.push_cow(mem::take(t));
307                    self.advance()?;
308                }
309                _ => {
310                    self.advance()?;
311                }
312            }
313        }
314
315        debug!("consumed text content: {:?}", text.as_str());
316        Ok(text.into_cow())
317    }
318
319    fn do_map<'r, V>(
320        &'r mut self,
321        visitor: V,
322        emit_value: bool,
323    ) -> Result<V::Value, DeserializationError>
324    where
325        V: de::Visitor<'de>,
326    {
327        self.push_elt()?;
328        let stack_size = self.stack.len();
329        let value = visitor.visit_map(MapAccess::new(self, emit_value))?;
330        self.check_stack_size(stack_size);
331        self.pop_elt()?;
332
333        Ok(value)
334    }
335
336    #[track_caller]
337    fn check_stack_size(&self, expected_size: usize) {
338        let stack = &self.stack;
339
340        debug_assert_eq!(
341            expected_size,
342            stack.len(),
343            "unstable stack: {action} {delta:?}",
344            action = if stack.len() > expected_size {
345                "added"
346            } else {
347                "removed"
348            },
349            delta = stack.iter().skip(expected_size).collect::<Vec<_>>(),
350        );
351    }
352}
353
354macro_rules! forward_parse {
355    ($deserialize:ident => $visit:ident) => {
356        fn $deserialize<V>(self, visitor: V) -> Result<V::Value, DeserializationError>
357        where
358            V: de::Visitor<'de>,
359        {
360            trace!(stringify!($deserialize));
361            let value = self.consume_text::<V>()?.parse()?;
362            visitor.$visit(value)
363        }
364    };
365}
366
367impl<'de, 'r> Deserializer<'de> for &'r mut SgmlDeserializer<'de> {
368    type Error = DeserializationError;
369
370    forward_parse!(deserialize_i8 => visit_i8);
371    forward_parse!(deserialize_i16 => visit_i16);
372    forward_parse!(deserialize_i32 => visit_i32);
373    forward_parse!(deserialize_i64 => visit_i64);
374    forward_parse!(deserialize_u8 => visit_u8);
375    forward_parse!(deserialize_u16 => visit_u16);
376    forward_parse!(deserialize_u32 => visit_u32);
377    forward_parse!(deserialize_u64 => visit_u64);
378    forward_parse!(deserialize_f32 => visit_f32);
379    forward_parse!(deserialize_f64 => visit_f64);
380
381    fn deserialize_bool<V>(self, visitor: V) -> Result<V::Value, Self::Error>
382    where
383        V: de::Visitor<'de>,
384    {
385        trace!("deserialize_bool");
386
387        if let SgmlEvent::Attribute { name, value } = self.peek()? {
388            // Treat empty values and repetitions of the key as true values
389            let value = value.as_deref().unwrap_or_default();
390            if value.is_empty() || value.eq_ignore_ascii_case(name) {
391                self.advance()?;
392                return visitor.visit_bool(true);
393            }
394        }
395
396        let str = self.consume_text::<V>()?;
397        if str == "1" || str.eq_ignore_ascii_case("true") {
398            visitor.visit_bool(true)
399        } else if str == "0" || str.eq_ignore_ascii_case("false") {
400            visitor.visit_bool(false)
401        } else {
402            Err(de::Error::invalid_value(
403                Unexpected::Str(&str),
404                &"a boolean",
405            ))
406        }
407    }
408
409    fn deserialize_str<V>(self, visitor: V) -> Result<V::Value, Self::Error>
410    where
411        V: de::Visitor<'de>,
412    {
413        trace!("deserialize_str");
414        match self.consume_text::<V>()? {
415            Cow::Borrowed(s) => visitor.visit_borrowed_str(s),
416            Cow::Owned(s) => visitor.visit_string(s),
417        }
418    }
419
420    fn deserialize_string<V>(self, visitor: V) -> Result<V::Value, Self::Error>
421    where
422        V: de::Visitor<'de>,
423    {
424        trace!("deserialize_string -> str");
425        self.deserialize_str(visitor)
426    }
427
428    fn deserialize_char<V>(self, visitor: V) -> Result<V::Value, Self::Error>
429    where
430        V: de::Visitor<'de>,
431    {
432        trace!("deserialize_char -> str");
433        self.deserialize_str(visitor)
434    }
435
436    fn deserialize_bytes<V>(self, visitor: V) -> Result<V::Value, Self::Error>
437    where
438        V: de::Visitor<'de>,
439    {
440        trace!("deserialize_bytes -> str");
441        self.deserialize_str(visitor)
442    }
443
444    fn deserialize_byte_buf<V>(self, visitor: V) -> Result<V::Value, Self::Error>
445    where
446        V: de::Visitor<'de>,
447    {
448        trace!("deserialize_byte_buf -> str");
449        self.deserialize_str(visitor)
450    }
451
452    fn deserialize_identifier<V>(self, visitor: V) -> Result<V::Value, Self::Error>
453    where
454        V: de::Visitor<'de>,
455    {
456        trace!("deserialize_identifier -> str");
457        self.deserialize_str(visitor)
458    }
459
460    fn deserialize_option<V>(self, visitor: V) -> Result<V::Value, Self::Error>
461    where
462        V: de::Visitor<'de>,
463    {
464        visitor.visit_some(self)
465    }
466
467    fn deserialize_unit<V>(self, visitor: V) -> Result<V::Value, Self::Error>
468    where
469        V: de::Visitor<'de>,
470    {
471        if self.accumulated_text.take().is_some() {
472            trace!("deserialize_unit -> accumulated text");
473            return visitor.visit_unit();
474        }
475
476        trace!("deserialize_unit");
477        match self.peek()? {
478            SgmlEvent::OpenStartTag { .. } => {
479                self.push_elt()?;
480                self.pop_elt()?;
481                visitor.visit_unit()
482            }
483            SgmlEvent::Attribute { .. } => {
484                self.advance()?;
485                visitor.visit_unit()
486            }
487            _ => self.deserialize_any(visitor),
488        }
489    }
490
491    fn deserialize_unit_struct<V>(
492        self,
493        name: &'static str,
494        visitor: V,
495    ) -> Result<V::Value, Self::Error>
496    where
497        V: de::Visitor<'de>,
498    {
499        trace!("deserialize_unit_struct ({}) -> unit", name);
500        self.deserialize_unit(visitor)
501    }
502
503    fn deserialize_newtype_struct<V>(
504        self,
505        name: &'static str,
506        visitor: V,
507    ) -> Result<V::Value, Self::Error>
508    where
509        V: de::Visitor<'de>,
510    {
511        trace!("deserialize_newtype_struct ({})", name);
512        visitor.visit_newtype_struct(self)
513    }
514
515    fn deserialize_seq<V>(self, visitor: V) -> Result<V::Value, Self::Error>
516    where
517        V: de::Visitor<'de>,
518    {
519        trace!("deserialize_seq (tag: {:?})", self.map_key);
520        let stack_size = self.stack.len();
521
522        let tag_name = self.map_key.take().map(Into::into);
523        let value = visitor.visit_seq(SeqAccess::new(self, tag_name))?;
524
525        self.check_stack_size(stack_size);
526
527        Ok(value)
528    }
529
530    fn deserialize_tuple<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
531    where
532        V: de::Visitor<'de>,
533    {
534        trace!("deserialize_tuple ({} items) -> seq", len);
535        self.deserialize_seq(visitor)
536    }
537
538    fn deserialize_tuple_struct<V>(
539        self,
540        name: &'static str,
541        len: usize,
542        visitor: V,
543    ) -> Result<V::Value, Self::Error>
544    where
545        V: de::Visitor<'de>,
546    {
547        trace!("deserialize_tuple_struct({}, {} items) -> seq", name, len);
548        self.deserialize_seq(visitor)
549    }
550
551    fn deserialize_map<V>(self, visitor: V) -> Result<V::Value, Self::Error>
552    where
553        V: de::Visitor<'de>,
554    {
555        trace!("deserialize_map");
556        self.do_map(visitor, false)
557    }
558
559    fn deserialize_struct<V>(
560        self,
561        name: &'static str,
562        fields: &'static [&'static str],
563        visitor: V,
564    ) -> Result<V::Value, Self::Error>
565    where
566        V: de::Visitor<'de>,
567    {
568        trace!("deserialize_struct({}) -> map", name);
569        self.do_map(visitor, fields.contains(&"$value"))
570    }
571
572    fn deserialize_enum<V>(
573        self,
574        name: &'static str,
575        _variants: &'static [&'static str],
576        visitor: V,
577    ) -> Result<V::Value, Self::Error>
578    where
579        V: de::Visitor<'de>,
580    {
581        trace!("deserialize_enum({})", name);
582
583        let stack_size = self.stack.len();
584
585        // If true, we have a <map-key>(enum-value)</map-key> case;
586        // if false, it's (enum-value) directly
587        let enum_within_element = self
588            .map_key
589            .as_deref()
590            .and_then(|map_key| {
591                self.expect_start_tag()
592                    .ok()
593                    .map(|start_tag| start_tag == map_key)
594            })
595            .unwrap_or(false);
596
597        // If true, (enum-value) is <variant (fields)>(fields)</variant>;
598        // if false, (enum-value) is just a string
599        let use_tag_name_for_variant = if enum_within_element {
600            if self.peek_content_type()?.contains_child_elements {
601                trace!("enum within element; using content elt");
602                // <key><variant (fields)>(fields)</variant></key>
603                // Advance cursor to `<variant`
604                self.push_elt()?;
605                self.advance_to_content()?;
606                true
607            } else {
608                trace!("enum within element; using text content");
609                // <key>variant</key>
610                // Keep cursor on `<key`
611                false
612            }
613        } else {
614            // No surrounding element, so it must be <variant (fields)>(fields)</variant>
615            // Keep cursor on `<variant`
616            true
617        };
618
619        let value = visitor.visit_enum(EnumAccess::new(self, use_tag_name_for_variant))?;
620        if enum_within_element && use_tag_name_for_variant {
621            self.pop_elt()?;
622        }
623
624        self.check_stack_size(stack_size);
625        Ok(value)
626    }
627
628    fn deserialize_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
629    where
630        V: de::Visitor<'de>,
631    {
632        trace!("deserialize_any");
633
634        if self.accumulated_text.is_some() {
635            return self.deserialize_str(visitor);
636        }
637        match self.peek()? {
638            SgmlEvent::OpenStartTag { .. } => {
639                let content = self.peek_content_type()?;
640                if content.contains_child_elements {
641                    self.deserialize_map(visitor)
642                } else if content.contains_text {
643                    self.deserialize_str(visitor)
644                } else {
645                    self.deserialize_unit(visitor)
646                }
647            }
648            SgmlEvent::Attribute { .. } => self.deserialize_str(visitor),
649            _ => Err(DeserializationError::ExpectedStartTag),
650        }
651    }
652
653    fn deserialize_ignored_any<V>(self, visitor: V) -> Result<V::Value, Self::Error>
654    where
655        V: de::Visitor<'de>,
656    {
657        trace!("deserialize_ignored_any -> unit");
658        self.deserialize_unit(visitor)
659    }
660}
661
662impl de::Error for DeserializationError {
663    fn custom<T: fmt::Display>(msg: T) -> Self {
664        DeserializationError::Message(msg.to_string())
665    }
666}
667
668struct MapAccess<'de, 'r> {
669    de: &'r mut SgmlDeserializer<'de>,
670    stack_size: usize,
671    map_key: Option<Rc<str>>,
672    content_strategy: ContentStrategy,
673    text_content: Option<CowBuffer<'de>>,
674    next_entry_is_dollarvalue: bool,
675}
676
677impl<'de, 'r> MapAccess<'de, 'r> {
678    fn new(de: &'r mut SgmlDeserializer<'de>, emit_value: bool) -> Self {
679        let stack_size = de.stack.len();
680        let content_strategy = if emit_value {
681            if de
682                .peek_content_type()
683                .map(|content| content.contains_child_elements)
684                .unwrap_or(false)
685            {
686                ContentStrategy::ElementsAreDollarValue
687            } else {
688                ContentStrategy::TextOnly
689            }
690        } else {
691            ContentStrategy::ElementsAreMapEntries
692        };
693        Self {
694            de,
695            stack_size,
696            map_key: None,
697            content_strategy,
698            text_content: (content_strategy == ContentStrategy::TextOnly).then(CowBuffer::new),
699            next_entry_is_dollarvalue: false,
700        }
701    }
702}
703
704#[derive(Clone, Copy, PartialEq)]
705enum ContentStrategy {
706    /// Element only contains text
707    TextOnly,
708    /// Treat element content as map entries
709    ElementsAreMapEntries,
710    /// Treat element content as the value for key `$value`
711    ElementsAreDollarValue,
712}
713
714impl<'de, 'r> de::MapAccess<'de> for MapAccess<'de, 'r> {
715    type Error = DeserializationError;
716
717    fn next_key_seed<K: de::DeserializeSeed<'de>>(
718        &mut self,
719        seed: K,
720    ) -> Result<Option<K::Value>, Self::Error> {
721        trace!("next_key_seed");
722        self.de.check_stack_size(self.stack_size);
723
724        loop {
725            break match self.de.peek_mut()? {
726                SgmlEvent::EndTag { .. } | SgmlEvent::XmlCloseEmptyElement => {
727                    if self.text_content.is_some() {
728                        self.next_entry_is_dollarvalue = true;
729                        debug!("next key: $value");
730                        self.map_key = Some("$value".into());
731                        seed.deserialize("$value".into_deserializer()).map(Some)
732                    } else {
733                        Ok(None)
734                    }
735                }
736                SgmlEvent::Attribute { name, .. } => {
737                    debug!("next key: {} (from attribute)", name);
738                    seed.deserialize(name.as_ref().into_deserializer())
739                        .map(Some)
740                }
741                SgmlEvent::CloseStartTag => {
742                    self.de.advance()?;
743                    continue;
744                }
745                SgmlEvent::OpenStartTag { name } => match self.content_strategy {
746                    ContentStrategy::ElementsAreMapEntries => {
747                        debug!("next key: {} (from tag name)", name);
748                        self.map_key = Some(name.clone().into_owned().into());
749                        seed.deserialize(name.as_ref().into_deserializer())
750                            .map(Some)
751                    }
752                    ContentStrategy::ElementsAreDollarValue => {
753                        debug!("next key: $value (for element {:?})", name);
754                        seed.deserialize("$value".into_deserializer()).map(Some)
755                    }
756                    ContentStrategy::TextOnly => unreachable!(),
757                },
758                SgmlEvent::Character(text) => {
759                    let text = mem::take(text);
760                    self.de.advance()?;
761                    if let Some(value_acc) = &mut self.text_content {
762                        value_acc.push_cow(text);
763                    }
764                    continue;
765                }
766                SgmlEvent::ProcessingInstruction(_)
767                | SgmlEvent::MarkupDeclaration { .. }
768                | SgmlEvent::MarkedSection { .. } => unreachable!(),
769            };
770        }
771    }
772
773    fn next_value_seed<V>(&mut self, seed: V) -> Result<V::Value, Self::Error>
774    where
775        V: de::DeserializeSeed<'de>,
776    {
777        trace!("next_value_seed (key={:?})", self.map_key);
778        self.de.check_stack_size(self.stack_size);
779
780        if self.next_entry_is_dollarvalue {
781            self.de.accumulated_text = Some(self.text_content.take().unwrap().into_cow());
782            let value = seed.deserialize(&mut *self.de)?;
783            self.de.accumulated_text = None;
784            Ok(value)
785        } else if let Ok(SgmlEvent::Attribute { .. }) = self.de.peek() {
786            seed.deserialize(&mut *self.de)
787        } else {
788            self.de.map_key = self.map_key.take();
789            let value = seed.deserialize(&mut *self.de)?;
790            self.de.map_key = None;
791            Ok(value)
792        }
793    }
794}
795
796struct SeqAccess<'de, 'r> {
797    de: &'r mut SgmlDeserializer<'de>,
798    stack_size: usize,
799    tag_name: Option<Rc<str>>,
800}
801
802impl<'de, 'r> SeqAccess<'de, 'r> {
803    fn new(de: &'r mut SgmlDeserializer<'de>, tag_name: Option<Rc<str>>) -> Self {
804        let stack_size = de.stack.len();
805        Self {
806            de,
807            stack_size,
808            tag_name,
809        }
810    }
811}
812
813impl<'de, 'r> de::SeqAccess<'de> for SeqAccess<'de, 'r> {
814    type Error = DeserializationError;
815
816    fn next_element_seed<T: de::DeserializeSeed<'de>>(
817        &mut self,
818        seed: T,
819    ) -> Result<Option<T::Value>, Self::Error> {
820        self.de.check_stack_size(self.stack_size);
821
822        loop {
823            match self.de.peek()? {
824                SgmlEvent::OpenStartTag { name } => match &self.tag_name {
825                    Some(expected_tag) if name.as_ref() != expected_tag.as_ref() => {
826                        return Ok(None)
827                    }
828                    _ => {
829                        if self.de.map_key != self.tag_name {
830                            self.de.map_key = self.tag_name.clone();
831                        }
832                        return Ok(Some(seed.deserialize(&mut *self.de)?));
833                    }
834                },
835                SgmlEvent::Character(text) if text.is_empty() => self.de.advance()?,
836                _ => return Ok(None),
837            };
838        }
839    }
840}
841
842struct EnumAccess<'de, 'r> {
843    de: &'r mut SgmlDeserializer<'de>,
844    use_tag_name_for_variant: bool,
845}
846
847impl<'de, 'r> EnumAccess<'de, 'r> {
848    fn new(de: &'r mut SgmlDeserializer<'de>, use_tag_name_for_variant: bool) -> Self {
849        Self {
850            de,
851            use_tag_name_for_variant,
852        }
853    }
854}
855
856impl<'de, 'r> de::EnumAccess<'de> for EnumAccess<'de, 'r> {
857    type Error = DeserializationError;
858    type Variant = Self;
859
860    fn variant_seed<V>(self, seed: V) -> Result<(V::Value, Self::Variant), DeserializationError>
861    where
862        V: de::DeserializeSeed<'de>,
863    {
864        trace!("variant_seed");
865        let name = if self.use_tag_name_for_variant {
866            debug!("using tag name for enum variant");
867            let name = self.de.expect_start_tag()?.as_ref();
868            seed.deserialize(name.into_deserializer())
869        } else {
870            debug!("using text content for enum variant");
871            seed.deserialize(&mut *self.de)
872        }?;
873        Ok((name, self))
874    }
875}
876
877impl<'de, 'r> de::VariantAccess<'de> for EnumAccess<'de, 'r> {
878    type Error = DeserializationError;
879
880    fn unit_variant(self) -> Result<(), Self::Error> {
881        trace!("unit_variant");
882        if self.use_tag_name_for_variant {
883            self.de.push_elt()?;
884            self.de.pop_elt()?;
885        }
886        Ok(())
887    }
888
889    fn newtype_variant_seed<T: de::DeserializeSeed<'de>>(
890        self,
891        seed: T,
892    ) -> Result<T::Value, Self::Error> {
893        trace!("newtype_variant");
894        seed.deserialize(self.de)
895    }
896
897    fn tuple_variant<V>(self, len: usize, visitor: V) -> Result<V::Value, Self::Error>
898    where
899        V: de::Visitor<'de>,
900    {
901        trace!("tuple_variant({} items)", len);
902        if self.use_tag_name_for_variant {
903            self.de.map_key = Some(self.de.expect_start_tag()?.clone().into_owned().into());
904        }
905        self.de.deserialize_seq(visitor)
906    }
907
908    fn struct_variant<V>(
909        self,
910        fields: &'static [&'static str],
911        visitor: V,
912    ) -> Result<V::Value, Self::Error>
913    where
914        V: de::Visitor<'de>,
915    {
916        trace!("struct_variant");
917        self.de.do_map(visitor, fields.contains(&"$value"))
918    }
919}
920
921#[derive(Debug)]
922struct PeekContentType {
923    contains_text: bool,
924    contains_child_elements: bool,
925}