use std::fmt;
use std::str::FromStr;
use crate::errors::ParseError;
use crate::math::Point;
use crate::timing::Millis;
#[non_exhaustive]
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub enum Event {
Background(BackgroundEvent),
Video(VideoEvent),
Break(BreakEvent),
Storyboard(String),
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BackgroundEvent {
pub filename: String,
pub offset: Point<i32>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct VideoEvent {
pub start_time: Millis,
pub filename: String,
pub offset: Point<i32>,
}
#[derive(Clone, Debug, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
pub struct BreakEvent {
pub start_time: Millis,
pub end_time: Millis,
}
impl FromStr for Event {
type Err = ParseError;
fn from_str(line: &str) -> Result<Self, Self::Err> {
let parts = line.split(',').collect::<Vec<_>>();
let evt_type = parts[0];
Ok(match evt_type {
"0" => {
let filename = parts[2].trim_matches('"').to_string();
let offset = if let (Some(x), Some(y)) = (parts.get(3), parts.get(4)) {
let x_offset = x.parse::<i32>()?;
let y_offset = y.parse::<i32>()?;
Point::new(x_offset, y_offset)
} else {
Point::new(0, 0)
};
Event::Background(BackgroundEvent { filename, offset })
}
"1" | "Video" => {
let start_time = parts[1].parse::<i32>()?;
let filename = parts[2].trim_matches('"').to_string();
let offset = if let (Some(x), Some(y)) = (parts.get(3), parts.get(4)) {
let x_offset = x.parse::<i32>()?;
let y_offset = y.parse::<i32>()?;
Point::new(x_offset, y_offset)
} else {
Point::new(0, 0)
};
Event::Video(VideoEvent {
start_time: Millis(start_time),
filename,
offset,
})
}
"2" | "Break" => {
let start_time = parts[1].parse::<i32>()?;
let end_time = parts[2].parse::<i32>()?;
Event::Break(BreakEvent {
start_time: Millis(start_time),
end_time: Millis(end_time),
})
}
_ => Event::Storyboard(line.to_string()),
})
}
}
impl fmt::Display for Event {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Event::Background(evt) => write!(
f,
"0,0,{:?},{},{}",
evt.filename, evt.offset.x, evt.offset.y
)?,
Event::Video(evt) => write!(
f,
"1,{},{:?},{},{}",
evt.start_time.0, evt.filename, evt.offset.x, evt.offset.y
)?,
Event::Break(evt) => {
write!(f, "2,{},{}", evt.start_time.0, evt.end_time.0)?
}
Event::Storyboard(line) => write!(f, "{}", line)?,
}
Ok(())
}
}