diff options
Diffstat (limited to 'src/server.rs')
-rw-r--r-- | src/server.rs | 124 |
1 files changed, 124 insertions, 0 deletions
diff --git a/src/server.rs b/src/server.rs new file mode 100644 index 0000000..83b9151 --- /dev/null +++ b/src/server.rs @@ -0,0 +1,124 @@ +use std::fs; +use std::sync::Arc; + +use anyhow::anyhow; + +use http_types::mime; +use tide::prelude::*; +use tide::Request; + +use crate::datafiles::*; +use crate::format::*; +use crate::*; + +pub async fn server_main() -> tide::Result<()> { + // ---- load data files ---- + + eprintln!("Loading JMdict_e.xml..."); + let jmdict_raw = fs::read_to_string("data/JMdict_e.xml").expect("read_jmdict"); + let jmdict_raw: &'static str = String::leak(jmdict_raw); + + eprintln!("Parsing JMdict_e.xml..."); + let jmdict = roxmltree::Document::parse_with_options( + &jmdict_raw, + roxmltree::ParsingOptions { + allow_dtd: true, + ..Default::default() + }, + ) + .expect("parse_jmdict"); + let jmdict_xml = Box::leak(Box::new(jmdict)); + + eprintln!("Indexing JMdict_e.xml..."); + let jmdict_idx = index_jmdict(jmdict_xml); + + eprintln!("Loading batches.json..."); + let batches = read_batches().expect("read/parse"); + let batches = Box::leak(batches.into_boxed_slice()); + + eprintln!("Loading kanji levels..."); + let kanji_levels = read_kanji_levels().expect("read_kanji_levels"); + + let mut index_bytes = Vec::new(); + format_index_to(&mut index_bytes, &batches, &kanji_levels).unwrap(); + let index = String::leak(String::from_utf8(index_bytes).unwrap()); + + // ---- setup http server ---- + + let state = Arc::new(StateStruct { + jmdict_raw, + jmdict_xml, + jmdict_idx, + batches, + index, + }); + + let mut app = tide::with_state(state); + app.with(tide::log::LogMiddleware::new()); + + app.at("/").get(home_page); + app.at("/index.html").get(home_page); + app.at("/style.css").serve_file("static/style.css")?; + app.at("/about.html").get(about_page); + app.at("/:batch").get(batch_page); + + // ---- serve actual http ---- + + eprintln!("Server listening on 127.0.0.1:8080"); + app.listen("127.0.0.1:8080").await?; + + Ok(()) +} + +type State = Arc<StateStruct>; +#[allow(dead_code)] +struct StateStruct { + jmdict_raw: &'static str, + jmdict_xml: &'static roxmltree::Document<'static>, + jmdict_idx: DictIndex<'static>, + batches: &'static [Batch], + index: &'static str, +} + +async fn home_page(req: Request<State>) -> tide::Result { + Ok(tide::Response::builder(200) + .body(req.state().index) + .content_type(mime::HTML) + .build()) +} + +async fn about_page(_req: Request<State>) -> tide::Result { + let mut about = Vec::new(); + format_about_to(&mut about)?; + Ok(tide::Response::builder(200) + .body(about) + .content_type(mime::HTML) + .build()) +} + +async fn batch_page(req: Request<State>) -> tide::Result { + let batch_idx = req.param("batch")?; + let batch_idx: usize = batch_idx + .strip_suffix(".html") + .unwrap_or(batch_idx) + .parse()?; + let batch = req + .state() + .batches + .get(batch_idx) + .ok_or(anyhow!("this batch number does not exist"))?; + + let mut buf = vec![]; + format_batch_to( + &mut buf, + &req.state().jmdict_idx, + req.state().batches.len(), + batch_idx, + batch, + )?; + + Ok(tide::Response::builder(200) + .body(buf) + .content_type(mime::HTML) + .build()) +} |