use crate::prelude::*;
use std::str::FromStr;
#[derive(PartialEq, Clone, Copy, Debug)]
pub struct Time {
pub hours: u32,
pub mins: u32,
}
impl Time {
pub fn new(hours: u32, mins: u32) -> Self {
Self { hours, mins }
}
}
impl FromStr for Time {
type Err = ParsingError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (_cur, hours, mins) = Cursor::from(s)
.digits(2..=2)
.parse_selection::<u32>() .char(':')
.digits(2..=2)
.parse_selection() .end_of_stream() .validate()?;
Ok(Time { hours, mins })
}
}
#[cfg(test)]
mod tests {
use super::*;
use test_log::test;
#[test]
fn test_parse_0923() {
assert_eq!(Time::from_str("09:23").unwrap(), Time::new(9, 23));
assert!(Time::from_str("09+23").is_err());
assert!(Time::from_str("09:23X").is_err());
}
#[test]
fn test_parse_three_times() -> Result<(), ParsingError> {
let s = "09:23 11:45 23:59";
let valid_chars: Vec<_> = "0123456789:".chars().collect();
let valid_chars = valid_chars.as_slice();
let (_c, t1, t2, t3) = Cursor::from(s)
.chars_in(1.., valid_chars)
.parse_selection::<Time>() .ws()
.chars_in(1.., valid_chars)
.parse_selection::<Time>()
.ws()
.chars_in(1.., valid_chars)
.parse_selection::<Time>()
.validate()?;
assert_eq!(t1, Time::new(9, 23));
assert_eq!(t2, Time::new(11, 45));
assert_eq!(t3, Time::new(23, 59));
Ok(())
}
}