use serde::{Deserialize, Serialize};
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
pub struct Length {
#[serde(rename = "$text")]
pub length: u32,
#[serde(rename = "@units")]
pub units: Units,
}
impl Length {
pub fn to_seconds(&self) -> u32 {
match self.units {
Units::Seconds => self.length,
Units::Minutes => self.length * 60,
Units::Hours => self.length * 3600,
}
}
pub fn to_minutes(&self) -> u32 {
match self.units {
Units::Seconds => self.length / 60,
Units::Minutes => self.length,
Units::Hours => self.length * 60,
}
}
pub fn to_hms(&self) -> (u8, u8, u8) {
let (h, m, s) = match self.units {
Units::Seconds => {
let (m, s) = divmod(self.length, 60);
let (h, m) = divmod(m, 60);
(h, m, s)
}
Units::Minutes => {
let (h, m) = divmod(self.length, 60);
(h, m, 0)
}
Units::Hours => (self.length, 0, 0),
};
(h.min(u32::from(u8::MAX)) as u8, m as u8, s as u8)
}
}
#[non_exhaustive]
#[derive(Debug, Clone, Copy, PartialEq, Serialize, Deserialize)]
#[serde(rename_all = "lowercase")]
#[repr(u8)]
pub enum Units {
Seconds,
Minutes,
Hours,
}
impl std::fmt::Display for Units {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Units::Seconds => f.write_str("seconds"),
Units::Minutes => f.write_str("minutes"),
Units::Hours => f.write_str("hours"),
}
}
}
fn divmod(x: u32, y: u32) -> (u32, u32) {
(x / y, x % y)
}