disco_quick/
video.rs

1use crate::parser::{Parser, ParserError};
2use crate::util::find_attr;
3use quick_xml::events::Event;
4use std::mem::take;
5
6#[derive(Clone, Debug, Default, PartialEq, Eq)]
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                        self.current_item.src = find_attr(e, b"src")?.to_string();
47                        self.current_item.duration = find_attr(e, b"duration")?.parse()?;
48                        self.current_item.embed = find_attr(e, b"embed")?.parse()?;
49                        ParserState::Video
50                    }
51                    b"title" => ParserState::Title,
52                    b"description" => ParserState::Description,
53                    _ => ParserState::Video,
54                },
55
56                Event::End(e) => match e.local_name().as_ref() {
57                    b"video" => {
58                        self.item_ready = true;
59                        ParserState::Video
60                    }
61                    _ => ParserState::Video,
62                },
63
64                _ => ParserState::Video,
65            },
66
67            ParserState::Title => match ev {
68                Event::Text(e) => {
69                    self.current_item.title = e.unescape()?.to_string();
70                    ParserState::Video
71                }
72                _ => ParserState::Video,
73            },
74
75            ParserState::Description => match ev {
76                Event::Text(e) => {
77                    self.current_item.description = e.unescape()?.to_string();
78                    ParserState::Video
79                }
80                _ => ParserState::Video,
81            },
82        };
83        Ok(())
84    }
85}