use chrono::{NaiveTime, Timelike};
use lazy_static::lazy_static;
use regex::Regex;
pub struct Chapter<'a> {
pub title: &'a str,
pub timestamp: NaiveTime,
}
impl<'a> Chapter<'a> {
pub fn as_secs(&self) -> u32 {
self.timestamp.hour() * 60 + self.timestamp.minute() * 60 + self.timestamp.second()
}
pub fn from(input: &'a str) -> Option<Vec<Self>> {
lazy_static! {
static ref REGEX: Regex = Regex::new(r"(\d{1,2}):(\d{2}) ?-? ?(\w.+)").unwrap();
}
let mut out = Vec::new();
for capture in REGEX.captures_iter(input) {
out.push(Chapter {
timestamp: NaiveTime::from_hms(
0,
capture.get(1).unwrap().as_str().parse().unwrap(),
capture.get(2).unwrap().as_str().parse().unwrap(),
),
title: capture.get(3).unwrap().as_str(),
});
}
return if out.len() == 0 { None } else { Some(out) };
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn find_nothing() {
assert!(Chapter::from("").is_none());
}
#[test]
fn find_exactly_one() {
let result = Chapter::from("0:00 - to the gateway").expect("No results");
assert_eq!(result.len(), 1);
assert_eq!(
result.first().unwrap().timestamp,
NaiveTime::from_hms(0, 0, 0),
);
assert_eq!(result.first().unwrap().title, "to the gateway");
}
#[test]
fn find_exactly_two() {
let result = Chapter::from(
r#"
0:00 - to the gateway
3:32 - star festival
"#,
)
.expect("No results");
assert_eq!(
result.get(1).unwrap().timestamp,
NaiveTime::from_hms(0, 3, 32),
);
assert_eq!(result.len(), 2);
}
#[test]
fn ignore_blank_lines() {
let result = Chapter::from(
r#"
0:00 - to the gateway
3:32 - star festival
"#,
)
.expect("No results");
assert_eq!(result.len(), 2);
}
}