use std::str::FromStr;
use crate::cookbook::{ch_2_simple_example::Time, ch_7_alternate::parse_clock};
use crate::prelude::Cursor;
use crate::prelude::*;
#[derive(Debug, PartialEq)]
struct TimePeriod(Time, Time);
impl FromStr for TimePeriod {
type Err = ParsingError;
fn from_str(s: &str) -> Result<Self, Self::Err> {
let (_c, time1, time2) = Cursor::from(s)
.debug_context("time period")
.chars_any(5..=5)
.parse_selection() .text("-")
.chars_any(5..=5)
.parse_selection() .end_of_stream()
.validate()?;
Ok(TimePeriod(time1, time2))
}
}
#[derive(Debug, PartialEq)]
struct TrainTime {
city: String,
arr: Time,
dep: Time,
}
fn parse_traintime(c: &str) -> Result<(&str, TrainTime), ParsingError> {
let (c, city, arr, dep) = Cursor::from(c)
.debug_context("train_time")
.word()
.parse_selection()
.ws()
.text("Arrive")
.ws()
.parse_with(parse_clock) .ws()
.text("Depart")
.ws()
.parse_with(|c| parse_clock(c)) .validate()?;
Ok((c, TrainTime { city, arr, dep }))
}
fn parse_timetable(s: &str) -> Result<Vec<TrainTime>, ParsingError> {
let mut vec = vec![];
for line in s.lines() {
let c = Cursor::from(line);
let (_c, tt) = c
.parse_with(parse_traintime)
.ws()
.end_of_stream() .validate()?;
vec.push(tt);
}
Ok(vec)
}
fn parse_str_clock(s: &str) -> Result<(&str, Time), ParsingError> {
Cursor::from(s).parse_with(parse_clock).validate()
}
fn parse_str_traintime(c: &str) -> Result<(&str, TrainTime), ParsingError> {
let (c, city, arr, dep) = Cursor::from(c)
.word()
.parse_selection()
.ws()
.text("Arrive")
.ws()
.parse_with(parse_str_clock) .ws()
.text("Depart")
.ws()
.parse_with(|c| parse_str_clock(c)) .validate()?;
Ok((c, TrainTime { city, arr, dep }))
}
#[cfg(test)]
mod tests {
use super::*;
use test_log::test;
#[test]
fn test_time_period() {
let tp: TimePeriod = ("13:00-14:30").parse().unwrap();
assert_eq!(tp, TimePeriod(Time::new(13, 00), Time::new(14, 30)));
}
#[test]
fn test_traintime() {
let c = "London Arrive 11:20 PM Depart 11:30 PM";
let (c, tt) = parse_traintime(c).unwrap();
assert_eq!(
tt,
TrainTime {
city: "London".to_string(),
arr: Time::new(23, 20),
dep: Time::new(23, 30)
}
);
assert_eq!(c, "");
}
#[test]
fn test_timetable() {
let s = "London Arrive 11:20 PM Depart 11:30 PM\nParis Arrive 13:05 Depart 13:10\nFrankfurt Arrive 10:30 Depart 10:35";
let table = parse_timetable(s).unwrap();
assert_eq!(table.len(), 3);
assert_eq!(table[2].city, "Frankfurt");
}
}