disco_quick/
video.rs

1use crate::parser::{Parser, ParserError};
2use crate::util::get_attr;
3use quick_xml::events::Event;
4use std::mem::take;
5
6#[derive(Clone, Debug, Default)]
7#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
8pub struct Video {
9    pub src: String,
10    pub duration: u32,
11    pub title: String,
12    pub description: String,
13    pub embed: bool,
14}
15
16#[derive(Debug, Default)]
17enum ParserState {
18    #[default]
19    Video,
20    Title,
21    Description,
22}
23
24#[derive(Debug, Default)]
25pub struct VideoParser {
26    state: ParserState,
27    pub current_item: Video,
28    pub item_ready: bool,
29}
30
31impl Parser for VideoParser {
32    type Item = Video;
33    fn new() -> Self {
34        Self::default()
35    }
36
37    fn take(&mut self) -> Video {
38        self.item_ready = false;
39        take(&mut self.current_item)
40    }
41    fn process(&mut self, ev: Event) -> Result<(), ParserError> {
42        self.state = match self.state {
43            ParserState::Video => match ev {
44                Event::Start(e) => match e.local_name().as_ref() {
45                    b"video" => {
46                        let mut attrs = e.attributes();
47                        self.current_item.src = get_attr(attrs.next()).to_string();
48                        self.current_item.duration = get_attr(attrs.next()).parse()?;
49                        self.current_item.embed = get_attr(attrs.next()).parse()?;
50                        ParserState::Video
51                    }
52                    b"title" => ParserState::Title,
53                    b"description" => ParserState::Description,
54                    _ => ParserState::Video,
55                },
56
57                Event::End(e) => match e.local_name().as_ref() {
58                    b"video" => {
59                        self.item_ready = true;
60                        ParserState::Video
61                    }
62                    _ => ParserState::Video,
63                },
64
65                _ => ParserState::Video,
66            },
67
68            ParserState::Title => match ev {
69                Event::Text(e) => {
70                    self.current_item.title = e.unescape()?.to_string();
71                    ParserState::Video
72                }
73                _ => ParserState::Video,
74            },
75
76            ParserState::Description => match ev {
77                Event::Text(e) => {
78                    self.current_item.description = e.unescape()?.to_string();
79                    ParserState::Video
80                }
81                _ => ParserState::Video,
82            },
83        };
84        Ok(())
85    }
86}