aboutsummaryrefslogtreecommitdiff
path: root/src/server.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/server.rs')
-rw-r--r--src/server.rs124
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())
+}