diff options
author | Finn Behrens <me@kloenk.de> | 2020-11-15 18:02:07 +0100 |
---|---|---|
committer | Finn Behrens <me@kloenk.de> | 2020-11-15 18:02:07 +0100 |
commit | 411fd3c067235a7a2b0ae6668970e003e82ce146 (patch) | |
tree | 83f3c85a4adc58488f581926afecdc53b48e1f1f | |
parent | 14f604adcaa5e863f7a660b944b6ea929314ccf0 (diff) | |
download | backend-411fd3c067235a7a2b0ae6668970e003e82ce146.tar.gz backend-411fd3c067235a7a2b0ae6668970e003e82ce146.tar.xz backend-411fd3c067235a7a2b0ae6668970e003e82ce146.zip |
add slp entry struct
-rw-r--r-- | Cargo.lock | 192 | ||||
-rw-r--r-- | Cargo.toml | 8 | ||||
-rw-r--r-- | src/dsb/html.rs | 8 | ||||
-rw-r--r-- | src/dsb/mod.rs | 6 | ||||
-rw-r--r-- | src/error.rs | 83 | ||||
-rw-r--r-- | src/lib.rs | 7 | ||||
-rw-r--r-- | src/main.rs | 10 | ||||
-rw-r--r-- | src/slp/mod.rs | 0 | ||||
-rw-r--r-- | src/types.rs | 252 |
9 files changed, 516 insertions, 50 deletions
@@ -1,6 +1,26 @@ # This file is automatically @generated by Cargo. # It is not intended for manual editing. [[package]] +name = "aho-corasick" +version = "0.7.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7404febffaa47dac81aa44dba71523c9d069b1bdc50a77db41195149e17f68e5" +dependencies = [ + "memchr", +] + +[[package]] +name = "atty" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d9b39be18770d11421cdb1b9947a45dd3f37e93092cbf377614828a319d5fee8" +dependencies = [ + "hermit-abi", + "libc", + "winapi", +] + +[[package]] name = "autocfg" version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -11,13 +31,20 @@ name = "backend" version = "0.1.0" dependencies = [ "chrono", - "custom_error", "html5ever", + "libc", "log", "markup5ever_rcdom", + "pretty_env_logger", ] [[package]] +name = "bumpalo" +version = "3.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2e8c087f005730276d1096a652e92a8bacee2e2472bcc9715a74d2bec38b5820" + +[[package]] name = "cfg-if" version = "0.1.10" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -29,18 +56,27 @@ version = "0.4.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "670ad68c9088c2a963aaa298cb369688cf3f9465ce5e2d4ca10e6e0098a1ce73" dependencies = [ + "js-sys", "libc", "num-integer", "num-traits", "time", + "wasm-bindgen", "winapi", ] [[package]] -name = "custom_error" -version = "1.8.0" +name = "env_logger" +version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "51ac5e99a7fea3ee8a03fa4721a47e2efd3fbb38358fc61192a54d4c6f866c12" +checksum = "44533bbbb3bb3c1fa17d9f2e4e38bbbaf8396ba82193c4cb1b6445d711445d36" +dependencies = [ + "atty", + "humantime", + "log", + "regex", + "termcolor", +] [[package]] name = "futf" @@ -64,6 +100,15 @@ dependencies = [ ] [[package]] +name = "hermit-abi" +version = "0.1.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5aca5565f760fb5b220e499d72710ed156fdb74e631659e99377d9ebfbd13ae8" +dependencies = [ + "libc", +] + +[[package]] name = "html5ever" version = "0.25.1" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -78,12 +123,30 @@ dependencies = [ ] [[package]] +name = "humantime" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df004cfca50ef23c36850aaaa59ad52cc70d0e90243c3c7737a4dd32dc7a3c4f" +dependencies = [ + "quick-error", +] + +[[package]] name = "itoa" version = "0.4.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6" [[package]] +name = "js-sys" +version = "0.3.45" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca059e81d9486668f12d455a4ea6daa600bd408134cd17e3d3fb5a32d1f016f8" +dependencies = [ + "wasm-bindgen", +] + +[[package]] name = "lazy_static" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -140,6 +203,12 @@ dependencies = [ ] [[package]] +name = "memchr" +version = "2.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ee1c47aaa256ecabcaea351eae4a9b01ef39ed810004e298d2511ed284b1525" + +[[package]] name = "new_debug_unreachable" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -215,6 +284,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" [[package]] +name = "pretty_env_logger" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "926d36b9553851b8b0005f1275891b392ee4d2d833852c417ed025477350fb9d" +dependencies = [ + "env_logger", + "log", +] + +[[package]] name = "proc-macro2" version = "1.0.24" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -224,6 +303,12 @@ dependencies = [ ] [[package]] +name = "quick-error" +version = "1.2.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a1d01941d82fa2ab50be1e79e6714289dd7cde78eba4c074bc5a4374f650dfe0" + +[[package]] name = "quote" version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -284,6 +369,24 @@ dependencies = [ ] [[package]] +name = "regex" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38cf2c13ed4745de91a5eb834e11c00bcc3709e773173b2ce4c56c9fbde04b9c" +dependencies = [ + "aho-corasick", + "memchr", + "regex-syntax", + "thread_local", +] + +[[package]] +name = "regex-syntax" +version = "0.6.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b181ba2dcf07aaccad5448e8ead58db5b742cf85dfe035e2227f137a539a189" + +[[package]] name = "ryu" version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -371,6 +474,24 @@ dependencies = [ ] [[package]] +name = "termcolor" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb6bfa289a4d7c5766392812c0a1f4c1ba45afa1ad47803c11e1f407d846d75f" +dependencies = [ + "winapi-util", +] + +[[package]] +name = "thread_local" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d40c6d1b69745a6ec6fb1ca717914848da4b44ae29d9b3080cbee91d72a69b14" +dependencies = [ + "lazy_static", +] + +[[package]] name = "time" version = "0.1.44" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -406,6 +527,60 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a143597ca7c7793eff794def352d41792a93c481eb1042423ff7ff72ba2c31f" [[package]] +name = "wasm-bindgen" +version = "0.2.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ac64ead5ea5f05873d7c12b545865ca2b8d28adfc50a49b84770a3a97265d42" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f22b422e2a757c35a73774860af8e112bff612ce6cb604224e8e47641a9e4f68" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b13312a745c08c469f0b292dd2fcd6411dba5f7160f593da6ef69b64e407038" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f249f06ef7ee334cc3b8ff031bfc11ec99d00f34d86da7498396dc1e3b1498fe" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d649a3145108d7d3fbcde896a468d1bd636791823c9921135218ad89be08307" + +[[package]] name = "winapi" version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -422,6 +597,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] +name = "winapi-util" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +dependencies = [ + "winapi", +] + +[[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -6,13 +6,17 @@ edition = "2018" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html +[lib] +crate-type = ["cdylib"] + [features] scraper = [] default = [] [dependencies] -chrono = { version = "0.4" } -custom_error = "1.8" +chrono = { version = "0.4", features = [ "wasmbind" ] } log = "0.4" +pretty_env_logger = "0.4" html5ever = "0.25" markup5ever_rcdom = "0.1" +libc = "*" diff --git a/src/dsb/html.rs b/src/dsb/html.rs index 670ce07..5899971 100644 --- a/src/dsb/html.rs +++ b/src/dsb/html.rs @@ -119,9 +119,9 @@ fn new_mon_head(node: &Node) -> Result<DSB, Error> { Ok(DSB { school, year, - valid_from, - updated_at, - date: chrono::NaiveDate::from_ymd(1970, 1, 1), + valid_from: valid_from.into(), + updated_at: updated_at.into(), + date: chrono::NaiveDate::from_ymd(1970, 1, 1).into(), week: Week::A, // TODO: ?? free_lessons: None, missing_teachers: Vec::new(), @@ -134,7 +134,7 @@ fn new_mon_head(node: &Node) -> Result<DSB, Error> { fn parse_mon_title(dsb: &mut DSB, info: &str) -> Result<(), Error> { dsb.week = Week::try_from(info.as_bytes()[info.len() - 1] as char)?; let strs = info.split_ascii_whitespace().collect::<Vec<&str>>(); - dsb.date = chrono::NaiveDate::parse_from_str(strs[0], "%d.%m.%Y")?; + dsb.date = chrono::NaiveDate::parse_from_str(strs[0], "%d.%m.%Y")?.into(); Ok(()) } diff --git a/src/dsb/mod.rs b/src/dsb/mod.rs index 4ee8521..2dbfafd 100644 --- a/src/dsb/mod.rs +++ b/src/dsb/mod.rs @@ -15,11 +15,11 @@ use hyper::Client; pub struct DSB { pub school: String, pub year: String, - pub valid_from: chrono::NaiveDate, - pub updated_at: chrono::NaiveDateTime, + pub valid_from: NaiveDate, + pub updated_at: NaiveDateTime, /// Day this entry affects - pub date: chrono::NaiveDate, + pub date: NaiveDate, pub week: Week, pub free_lessons: Option<String>, pub missing_teachers: Vec<Teacher>, diff --git a/src/error.rs b/src/error.rs index a7c2e0d..7092b01 100644 --- a/src/error.rs +++ b/src/error.rs @@ -1,14 +1,77 @@ -use custom_error::custom_error; +use std::fmt; -custom_error! { pub Error - DsbParse { msg: String } = "Failed to parse dsb: {msg}", - DsbInvalidWeek{ value: String } = "Week {value} is invalid", - DsbInvalidHour{ value: String } = "Hour {value} is invalid", - InvalidRoom{ value: String } = "Room {value} is invalid", - InvalidCourse { value: String} = "Course {value} is invalid", +#[derive(Debug)] +pub enum Error { + DsbParse(String), + InvalidWeek(String), + InvalidHour(String), + InvalidRoom(String), + InvalidCourse(String), + InvalidTrack(String), + ChronoParse(chrono::ParseError), + ParseInt(std::num::ParseIntError), - ChronoParse { source: chrono::ParseError } = "Chrono: {source}", - Parse{ source: std::num::ParseIntError } = "Parser: {source}", - Io{source: std::io::Error } = "IO: {source}" + Io(std::io::Error), +} + +impl Error { + #[no_mangle] + pub extern "C" fn err_to_string(&self) -> *const libc::c_char { + let str = self.to_string(); + let str = std::ffi::CString::new(str).unwrap(); + str.as_ptr() + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + use Error::*; + match self { + DsbParse(v) => write!(f, "Failed to parse dsb: {}", v), + InvalidWeek(v) => write!(f, "Week '{}' is invalid", v), + InvalidHour(v) => write!(f, "Hour '{}' is invalid", v), + InvalidRoom(v) => write!(f, "Room '{}' is invalid", v), + InvalidCourse(v) => write!(f, "Course '{}', is invalid", v), + InvalidTrack(v) => write!(f, "Track '{}' is invalid", v), + + ChronoParse(e) => write!(f, "Chrono: {}", e), + ParseInt(e) => write!(f, "Parse: {}", e), + + Io(e) => write!(f, "IO: {}", e), + } + } +} + +impl std::error::Error for Error { + fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + use Error::*; + match self { + ChronoParse(e) => Some(e), + ParseInt(e) => Some(e), + Io(e) => Some(e), + _ => None, + } + } + /*fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { + self.source.as_ref() + }*/ +} + +impl std::convert::From<std::io::Error> for Error { + fn from(e: std::io::Error) -> Self { + Error::Io(e) + } +} + +impl std::convert::From<chrono::ParseError> for Error { + fn from(e: chrono::ParseError) -> Self { + Error::ChronoParse(e) + } +} + +impl std::convert::From<std::num::ParseIntError> for Error { + fn from(e: std::num::ParseIntError) -> Self { + Error::ParseInt(e) + } } @@ -9,11 +9,10 @@ pub use error::Error; #[macro_export] macro_rules! err_dsb_parse { ($fmt:expr) => ({ - $crate::error::Error::DsbParse{ msg: ($fmt). - to_string() } + $crate::error::Error::DsbParse(($fmt).to_string()) }); ($fmt:expr, $($arg:tt)*) => ({ - $crate::error::Error::DsbParse{ msg: format! - ($fmt, $($arg)*) } + $crate::error::Error::DsbParse(format! + ($fmt, $($arg)*)) }); } diff --git a/src/main.rs b/src/main.rs index e7a11a9..8a4b30b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,11 @@ fn main() { - println!("Hello, world!"); + init_logger(); + log::info!("starting backend"); +} + +fn init_logger() { + if let Err(_) = std::env::var("RUST_LOG") { + std::env::set_var("RUST_LOG", "info"); + } + pretty_env_logger::init_timed(); } diff --git a/src/slp/mod.rs b/src/slp/mod.rs new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/src/slp/mod.rs diff --git a/src/types.rs b/src/types.rs index 6d50af1..ad41391 100644 --- a/src/types.rs +++ b/src/types.rs @@ -18,7 +18,7 @@ impl TryFrom<char> for Week { match value.as_str() { "A" => Ok(Week::A), "B" => Ok(Week::B), - _ => Err(Error::DsbInvalidWeek { value }), + _ => Err(Error::InvalidWeek(value)), } } } @@ -27,15 +27,16 @@ impl TryFrom<&str> for Week { type Error = Error; fn try_from(value: &str) -> Result<Self, Self::Error> { - let value = value.to_uppercase().to_string(); + let value = value.to_uppercase(); match value.as_str() { "A" => Ok(Week::A), "B" => Ok(Week::B), - _ => Err(Error::DsbInvalidWeek { value }), + _ => Err(Error::InvalidWeek(value)), } } } +#[repr(C)] #[derive(Clone, PartialEq, Eq)] pub struct Class { pub name: String, @@ -59,6 +60,38 @@ pub enum Hour { Block(u8, u8), } +impl Hour { + #[export_name = "hour_is_part"] + pub extern "C" fn is_part(&self) -> bool { + match self { + Hour::Part(_) => true, + Hour::Block(_, _) => false, + } + } + #[export_name = "hour_is_block"] + pub extern "C" fn is_block(&self) -> bool { + match self { + Hour::Part(_) => false, + Hour::Block(_, _) => true, + } + } + + #[export_name = "hour_starts"] + pub extern "C" fn starts(&self) -> u8 { + match self { + Hour::Part(v) => *v, + Hour::Block(v, _) => *v, + } + } + #[export_name = "hour_ends"] + pub extern "C" fn ends(&self) -> u8 { + match self { + Hour::Part(v) => *v, + Hour::Block(_, v) => *v, + } + } +} + impl TryFrom<&str> for Hour { type Error = Error; @@ -66,9 +99,7 @@ impl TryFrom<&str> for Hour { if value.contains('-') { let vec: Vec<&str> = value.split('-').map(|v| v.trim()).collect(); if vec.len() != 2 { - return Err(Error::DsbInvalidHour { - value: value.to_string(), - }); + return Err(Error::InvalidHour(value.to_string())); } Ok(Hour::Block(vec[0].parse()?, vec[1].parse()?)) } else { @@ -77,6 +108,7 @@ impl TryFrom<&str> for Hour { } } +#[repr(C, u8)] #[derive(Debug, PartialEq, Eq, Clone)] pub enum Kind { None, @@ -105,6 +137,7 @@ impl From<&str> for Kind { } } +#[repr(C, u8)] #[derive(Debug, Clone, PartialEq, Eq)] pub enum Room { A(u16), @@ -139,9 +172,7 @@ impl TryFrom<&str> for Room { } let cvalue = value.as_bytes(); if cvalue.len() != 4 { - return Err(Error::InvalidRoom { - value: value.to_string(), - }); + return Err(Error::InvalidRoom(value.to_string())); } match cvalue[0] as char { 'A' => Ok(Room::A(get_room_num(&cvalue[1..]))), @@ -149,9 +180,7 @@ impl TryFrom<&str> for Room { 'C' => Ok(Room::C(get_room_num(&cvalue[1..]))), 'D' => Ok(Room::D(get_room_num(&cvalue[1..]))), 'E' => Ok(Room::E(get_room_num(&cvalue[1..]))), - _ => Err(Error::InvalidRoom { - value: value.to_string(), - }), + _ => Err(Error::InvalidRoom(value.to_string())), } } } @@ -181,7 +210,7 @@ pub enum Course { Sec1(String), Sec2 { name: String, - track: Option<u8>, + track: Option<Track>, kind: CourseKind, }, // Sec2Exam?? @@ -191,9 +220,7 @@ impl Course { pub fn parse_sec2(value: &str) -> Result<Self, Error> { let vvalue = value.split('-').map(|v| v.trim()).collect::<Vec<&str>>(); if vvalue.len() != 2 { - return Err(Error::InvalidCourse { - value: value.to_string(), - }); + return Err(Error::InvalidCourse(value.to_string())); } let name = vvalue[0].to_string(); @@ -205,8 +232,46 @@ impl Course { track: None, }) } + + /// add a track to Sec2 + /// + /// # Panics + /// panics if self is a Sec1 course + pub fn add_track(&mut self, track: Track) { + let in_track = track; + if let Course::Sec2 { ref mut track, .. } = self { + *track = Some(in_track); + } else { + panic!("Course is sec1"); + } + } +} + +#[repr(C)] +#[derive(Debug, Clone, Eq, PartialEq)] +pub enum Track { + LK(u8), + GK(u8), +} + +impl TryFrom<&str> for Track { + type Error = Error; + + fn try_from(value: &str) -> Result<Self, Self::Error> { + let cvalue = value.as_bytes(); + if cvalue.len() != 2 { + return Err(Error::InvalidTrack(value.to_string())); + } + + match cvalue[0] as char { + 'G' => Ok(Track::GK(cvalue[1] as u8 - 48)), + 'L' => Ok(Track::LK(cvalue[1] as u8 - 48)), + _ => Err(Error::InvalidTrack(value.to_string())), + } + } } +#[repr(C)] #[derive(Debug, Clone, PartialEq, Eq)] pub enum CourseKind { GK(u8), @@ -219,9 +284,7 @@ impl TryFrom<&str> for CourseKind { fn try_from(value: &str) -> Result<Self, Self::Error> { let cvalue = value.as_bytes(); if cvalue.len() != 3 { - return Err(Error::InvalidCourse { - value: value.to_string(), - }); + return Err(Error::InvalidCourse(value.to_string())); } let v = cvalue[2] as u8 - 48; @@ -230,9 +293,7 @@ impl TryFrom<&str> for CourseKind { } else if value.starts_with("LK") { Ok(CourseKind::LK(v)) } else { - Err(Error::InvalidCourse { - value: value.to_string(), - }) + Err(Error::InvalidCourse(value.to_string())) } } } @@ -269,6 +330,102 @@ pub struct DsbEntry { pub room: Option<Room>, } +#[derive(Debug, Clone, PartialEq, Eq)] +pub struct SLPEntry { + /// Time for this entry + pub hour: Hour, + + /// Teacher for + pub teacher: Teacher, + + /// Course of this entry + pub course: Course, + + /// Room this is in + pub room: Room, +} + +impl SLPEntry { + pub fn parse(hour: Hour, value: &str) -> Result<Self, Error> { + // FIXME: teacher special cases + let value = value.trim(); + let value: Vec<&str> = value.split(' ').map(|v| v.trim()).collect(); + + let track = value[0]; + let sec2 = track.chars().nth(0) == Some('(') && track.chars().nth(3) == Some(')'); + + use std::convert::TryInto; + let room: Room = (*value.last().unwrap()).try_into()?; + + let teacher = Teacher { + name: value[value.len() - 2].to_string(), + }; + + //let course: Course = value[value.len() - 3].try_into()?; + let course = if sec2 { + let mut course = Course::parse_sec2(value[value.len() - 3])?; + course.add_track(Track::try_from(&value[0][1..3])?); + course + } else { + Course::Sec1(value[value.len() - 3].to_string()) + }; + + Ok(Self { + hour, + teacher, + room, + course, + }) + } +} + +use std::ops::{Deref, DerefMut}; +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct NaiveDate(chrono::NaiveDate); + +impl Deref for NaiveDate { + type Target = chrono::NaiveDate; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for NaiveDate { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl From<chrono::NaiveDate> for NaiveDate { + fn from(date: chrono::NaiveDate) -> Self { + Self(date) + } +} + +#[derive(Debug, Clone, PartialEq, Eq, PartialOrd, Ord)] +pub struct NaiveDateTime(chrono::NaiveDateTime); + +impl Deref for NaiveDateTime { + type Target = chrono::NaiveDateTime; + + fn deref(&self) -> &Self::Target { + &self.0 + } +} + +impl DerefMut for NaiveDateTime { + fn deref_mut(&mut self) -> &mut Self::Target { + &mut self.0 + } +} + +impl From<chrono::NaiveDateTime> for NaiveDateTime { + fn from(date_time: chrono::NaiveDateTime) -> Self { + Self(date_time) + } +} + #[cfg(test)] mod test { use super::{TryFrom, Week}; @@ -342,4 +499,55 @@ mod test { let v = super::get_room_num("301".as_bytes()); assert_eq!(v, 301); } + + #[test] + fn slp_entry() { + use super::Hour; + use super::SLPEntry; + let slp = SLPEntry::parse(Hour::Part(1), "(G3) GZ-GK1 TSA A207").unwrap(); + + assert_eq!(slp.hour, Hour::Part(1)); + assert_eq!( + slp.teacher, + super::Teacher { + name: "TSA".to_string() + } + ); + assert_eq!( + slp.course, + super::Course::Sec2 { + name: "GZ".to_string(), + track: Some(super::Track::GK(3)), + kind: super::CourseKind::GK(1), + } + ); + assert_eq!(slp.room, super::Room::A(207)); + } + + #[test] + fn slp_entry_sec1() { + use super::{Hour, SLPEntry}; + let slp = SLPEntry::parse(Hour::Part(1), "MU HRB B015").unwrap(); + + assert_eq!(slp.hour, Hour::Part(1)); + assert_eq!( + slp.teacher, + super::Teacher { + name: "HRB".to_string() + } + ); + assert_eq!(slp.course, super::Course::Sec1("MU".to_string())); + assert_eq!(slp.room, super::Room::B(15)); + } + + //#[test] // FIXME: create extra parse version for teacher, which takes the teacher as in input + fn slp_entry_teacher() { + use super::{Hour, SLPEntry}; + + let slp = SLPEntry::parse(Hour::Part(1), "5e IF A310").unwrap(); + assert_eq!(slp.hour, Hour::Part(1)); + + let slp = SLPEntry::parse(Hour::Part(2), "Q1-L2 IF-LK1 A306").unwrap(); + assert_eq!(slp.hour, Hour::Part(2)); + } } |