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}