aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFinn Behrens <me@kloenk.de>2020-11-15 18:02:07 +0100
committerFinn Behrens <me@kloenk.de>2020-11-15 18:02:07 +0100
commit411fd3c067235a7a2b0ae6668970e003e82ce146 (patch)
tree83f3c85a4adc58488f581926afecdc53b48e1f1f
parent14f604adcaa5e863f7a660b944b6ea929314ccf0 (diff)
downloadbackend-411fd3c067235a7a2b0ae6668970e003e82ce146.tar.gz
backend-411fd3c067235a7a2b0ae6668970e003e82ce146.tar.xz
backend-411fd3c067235a7a2b0ae6668970e003e82ce146.zip
add slp entry struct
-rw-r--r--Cargo.lock192
-rw-r--r--Cargo.toml8
-rw-r--r--src/dsb/html.rs8
-rw-r--r--src/dsb/mod.rs6
-rw-r--r--src/error.rs83
-rw-r--r--src/lib.rs7
-rw-r--r--src/main.rs10
-rw-r--r--src/slp/mod.rs0
-rw-r--r--src/types.rs252
9 files changed, 516 insertions, 50 deletions
diff --git a/Cargo.lock b/Cargo.lock
index fb8f6c0..da4ffd8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -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"
diff --git a/Cargo.toml b/Cargo.toml
index d2da93e..db9ca22 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -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)
+ }
}
diff --git a/src/lib.rs b/src/lib.rs
index bfffa31..9bcba6a 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -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));
+ }
}