From 0c30e065b678d41d8932b3bf0926608cfa15a7ac Mon Sep 17 00:00:00 2001 From: metamuffin Date: Tue, 10 Jan 2023 08:44:06 +0100 Subject: first listing --- Cargo.lock | 405 ++++++++++++++++++++++++++++++++++++++++-- Cargo.toml | 2 + src/frontend/pages/home.rs | 4 +- src/frontend/pages/layout.rs | 10 +- src/frontend/pages/mod.rs | 61 ++++++- src/frontend/pages/node.rs | 46 +++++ src/frontend/style/layout.css | 35 ++++ src/frontend/style/master.css | 0 src/frontend/style/mod.rs | 2 +- src/library.rs | 91 +++++++++- src/main.rs | 28 +-- 11 files changed, 641 insertions(+), 43 deletions(-) create mode 100644 src/frontend/pages/node.rs create mode 100644 src/frontend/style/layout.css delete mode 100644 src/frontend/style/master.css diff --git a/Cargo.lock b/Cargo.lock index 817fb9a..246f669 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -19,6 +19,29 @@ dependencies = [ "tokio-util", ] +[[package]] +name = "actix-files" +version = "0.6.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d832782fac6ca7369a70c9ee9a20554623c5e51c76e190ad151780ebea1cf689" +dependencies = [ + "actix-http", + "actix-service", + "actix-utils", + "actix-web", + "askama_escape", + "bitflags", + "bytes", + "derive_more", + "futures-core", + "http-range", + "log", + "mime", + "mime_guess", + "percent-encoding", + "pin-project-lite", +] + [[package]] name = "actix-http" version = "3.2.2" @@ -29,7 +52,7 @@ dependencies = [ "actix-rt", "actix-service", "actix-utils", - "ahash", + "ahash 0.7.6", "base64", "bitflags", "brotli", @@ -43,15 +66,15 @@ dependencies = [ "http", "httparse", "httpdate", - "itoa", + "itoa 1.0.5", "language-tags", "local-channel", "mime", "percent-encoding", "pin-project-lite", - "rand", + "rand 0.8.5", "sha1", - "smallvec", + "smallvec 1.10.0", "tracing", "zstd", ] @@ -143,7 +166,7 @@ dependencies = [ "actix-service", "actix-utils", "actix-web-codegen", - "ahash", + "ahash 0.7.6", "bytes", "bytestring", "cfg-if", @@ -153,7 +176,7 @@ dependencies = [ "futures-core", "futures-util", "http", - "itoa", + "itoa 1.0.5", "language-tags", "log", "mime", @@ -163,7 +186,7 @@ dependencies = [ "serde", "serde_json", "serde_urlencoded", - "smallvec", + "smallvec 1.10.0", "socket2", "time", "url", @@ -181,6 +204,56 @@ dependencies = [ "syn", ] +[[package]] +name = "actix-web-lab" +version = "0.18.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "55b7ac6309cfb46949171c49f7bc81d021310205a39bf0b0d0465e80a4857e3c" +dependencies = [ + "actix-files", + "actix-http", + "actix-router", + "actix-service", + "actix-utils", + "actix-web", + "actix-web-lab-derive", + "ahash 0.8.2", + "arc-swap", + "async-trait", + "bytes", + "bytestring", + "csv", + "derive_more", + "futures-core", + "futures-util", + "http", + "impl-more", + "itertools", + "local-channel", + "mediatype", + "mime", + "once_cell", + "pin-project-lite", + "regex", + "serde", + "serde_cbor_2", + "serde_html_form", + "serde_json", + "tokio", + "tracing", +] + +[[package]] +name = "actix-web-lab-derive" +version = "0.18.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e4419acd7924ac473ccd00a6efea324dd382b0b7ae31b8e06cd2c58d4d7afae6" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "adler" version = "1.0.2" @@ -198,6 +271,18 @@ dependencies = [ "version_check", ] +[[package]] +name = "ahash" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf6ccdb167abbf410dcb915cabd428929d7f6a04980b54a11f26a39f1c7f7107" +dependencies = [ + "cfg-if", + "getrandom", + "once_cell", + "version_check", +] + [[package]] name = "aho-corasick" version = "0.7.20" @@ -228,6 +313,29 @@ version = "1.0.68" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2cb2f989d18dd141ab8ae82f64d1a8cdd37e0840f73a406896cf5e99502fab61" +[[package]] +name = "arc-swap" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" + +[[package]] +name = "askama_escape" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "619743e34b5ba4e9703bba34deac3427c72507c7159f5fd030aea8cac0cfe341" + +[[package]] +name = "async-trait" +version = "0.1.61" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "705339e0e4a9690e2908d2b3d049d85682cf19fbd5782494498fbf7003a6a282" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "autocfg" version = "1.1.0" @@ -285,6 +393,18 @@ dependencies = [ "alloc-stdlib", ] +[[package]] +name = "bstr" +version = "0.2.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba3569f383e8f1598449f1a423e72e99569137b47740b1da11ef19af3d5c3223" +dependencies = [ + "lazy_static", + "memchr", + "regex-automata", + "serde", +] + [[package]] name = "byteorder" version = "1.4.3" @@ -321,6 +441,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "chashmap" +version = "2.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ff41a3c2c1e39921b9003de14bf0439c7b63a9039637c291e1a64925d8ddfa45" +dependencies = [ + "owning_ref", + "parking_lot 0.4.8", +] + [[package]] name = "convert_case" version = "0.4.0" @@ -388,6 +518,28 @@ dependencies = [ "typenum", ] +[[package]] +name = "csv" +version = "1.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22813a6dc45b335f9bade10bf7271dc477e81113e89eb251a0bc2a8a81c536e1" +dependencies = [ + "bstr", + "csv-core", + "itoa 0.4.8", + "ryu", + "serde", +] + +[[package]] +name = "csv-core" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2b2466559f260f48ad25fe6317b3c8dac77b5bdb5763ac7d9d6103530663bc90" +dependencies = [ + "memchr", +] + [[package]] name = "derive_more" version = "0.99.17" @@ -411,6 +563,12 @@ dependencies = [ "crypto-common", ] +[[package]] +name = "either" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "90e5c1c8368803113bf0c9584fc495a58b86dc8a29edbf8fe877d21d9507e797" + [[package]] name = "encoding_rs" version = "0.8.31" @@ -489,6 +647,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "fuchsia-cprng" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a06f77d526c1a601b7c4cdd98f54b5eaabffc14d5f2f0296febdc7f357c6d3ba" + [[package]] name = "futures-core" version = "0.3.25" @@ -517,6 +681,7 @@ dependencies = [ "futures-task", "pin-project-lite", "pin-utils", + "slab", ] [[package]] @@ -568,6 +733,12 @@ dependencies = [ "tracing", ] +[[package]] +name = "half" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eabb4a44450da02c90444cf74558da904edde8fb4e9035a9a6a4e15445af0bd7" + [[package]] name = "hashbrown" version = "0.12.3" @@ -591,9 +762,15 @@ checksum = "75f43d41e26995c17e71ee126451dd3941010b0514a81a9d11f3b341debc2399" dependencies = [ "bytes", "fnv", - "itoa", + "itoa 1.0.5", ] +[[package]] +name = "http-range" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "21dec9db110f5f872ed9699c3ecf50cf16f423502706ba5c72462e28d3157573" + [[package]] name = "httparse" version = "1.8.0" @@ -622,6 +799,12 @@ dependencies = [ "unicode-normalization", ] +[[package]] +name = "impl-more" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d14c422088773284a62e155b3e2f700a52cd3731dabe2cffd914e13f71b6bd4e" + [[package]] name = "indexmap" version = "1.9.2" @@ -663,6 +846,21 @@ dependencies = [ "windows-sys", ] +[[package]] +name = "itertools" +version = "0.10.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b0fd2260e829bddf4cb6ea802289de2f86d6a7a690192fbe91b3f46e0f2c8473" +dependencies = [ + "either", +] + +[[package]] +name = "itoa" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" + [[package]] name = "itoa" version = "1.0.5" @@ -674,7 +872,9 @@ name = "jellything" version = "0.1.0" dependencies = [ "actix-web", + "actix-web-lab", "anyhow", + "chashmap", "env_logger", "log", "markup", @@ -700,6 +900,12 @@ version = "0.3.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4345964bb142484797b161f473a503a434de77149dd8c7427788c6e13379388" +[[package]] +name = "lazy_static" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" + [[package]] name = "libc" version = "0.2.139" @@ -755,7 +961,7 @@ version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd9196a235d499738d04f6a2466ce2610bf6b84730610efea8bee1b90d028b0d" dependencies = [ - "itoa", + "itoa 1.0.5", "markup-proc-macro", ] @@ -770,6 +976,18 @@ dependencies = [ "syn", ] +[[package]] +name = "maybe-uninit" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60302e4db3a61da70c0cb7991976248362f30319e88850c487b9b95bbf059e00" + +[[package]] +name = "mediatype" +version = "0.19.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6a280afd79e5a4c3e7f298c6139321aad0365690f24a57539e18590b5a606966" + [[package]] name = "memchr" version = "2.5.0" @@ -791,6 +1009,16 @@ version = "0.3.16" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a60c7ce501c71e03a9c9c0d35b861413ae925bd979cc7a4e30d060069aaac8d" +[[package]] +name = "mime_guess" +version = "2.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4192263c238a5f0d0c6bfd21f336a313a4ce1c450542449ca191bb657b4642ef" +dependencies = [ + "mime", + "unicase", +] + [[package]] name = "miniz_oxide" version = "0.6.2" @@ -828,6 +1056,25 @@ version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6f61fba1741ea2b3d6a1e3178721804bb716a68a6aeba1149b5d52e3d464ea66" +[[package]] +name = "owning_ref" +version = "0.3.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" +dependencies = [ + "stable_deref_trait", +] + +[[package]] +name = "parking_lot" +version = "0.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "149d8f5b97f3c1133e3cfcd8886449959e856b557ff281e292b733d7c69e005e" +dependencies = [ + "owning_ref", + "parking_lot_core 0.2.14", +] + [[package]] name = "parking_lot" version = "0.11.2" @@ -849,6 +1096,18 @@ dependencies = [ "parking_lot_core 0.9.5", ] +[[package]] +name = "parking_lot_core" +version = "0.2.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4db1a8ccf734a7bce794cc19b3df06ed87ab2f3907036b693c68f56b4d4537fa" +dependencies = [ + "libc", + "rand 0.4.6", + "smallvec 0.6.14", + "winapi", +] + [[package]] name = "parking_lot_core" version = "0.8.6" @@ -859,7 +1118,7 @@ dependencies = [ "instant", "libc", "redox_syscall", - "smallvec", + "smallvec 1.10.0", "winapi", ] @@ -872,7 +1131,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "smallvec", + "smallvec 1.10.0", "windows-sys", ] @@ -944,6 +1203,19 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "rand" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "552840b97013b1a26992c11eac34bdd778e464601a4c2054b5f0bff7c6761293" +dependencies = [ + "fuchsia-cprng", + "libc", + "rand_core 0.3.1", + "rdrand", + "winapi", +] + [[package]] name = "rand" version = "0.8.5" @@ -952,7 +1224,7 @@ checksum = "34af8d1a0e25924bc5b7c43c079c942339d8f0a8b57c39049bef581b46327404" dependencies = [ "libc", "rand_chacha", - "rand_core", + "rand_core 0.6.4", ] [[package]] @@ -962,9 +1234,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e6c10a63a0fa32252be49d21e7709d4d4baf8d231c2dbce1eaa8141b9b127d88" dependencies = [ "ppv-lite86", - "rand_core", + "rand_core 0.6.4", ] +[[package]] +name = "rand_core" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a6fdeb83b075e8266dcc8762c22776f6877a63111121f5f8c7411e5be7eed4b" +dependencies = [ + "rand_core 0.4.2", +] + +[[package]] +name = "rand_core" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9c33a3c44ca05fa6f1807d8e6743f3824e8509beca625669633be0acbdf509dc" + [[package]] name = "rand_core" version = "0.6.4" @@ -974,6 +1261,15 @@ dependencies = [ "getrandom", ] +[[package]] +name = "rdrand" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "678054eb77286b51581ba43620cc911abf02758c91f93f479767aed0f90458b2" +dependencies = [ + "rand_core 0.3.1", +] + [[package]] name = "redox_syscall" version = "0.2.16" @@ -994,6 +1290,12 @@ dependencies = [ "regex-syntax", ] +[[package]] +name = "regex-automata" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c230d73fb8d8c1b9c0b3135c5142a8acee3a0558fb8db5cf1cb65f8d7862132" + [[package]] name = "regex-syntax" version = "0.6.28" @@ -1050,6 +1352,16 @@ dependencies = [ "serde_derive", ] +[[package]] +name = "serde_cbor_2" +version = "0.12.0-dev" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b46d75f449e01f1eddbe9b00f432d616fbbd899b809c837d0fbc380496a0dd55" +dependencies = [ + "half", + "serde", +] + [[package]] name = "serde_derive" version = "1.0.152" @@ -1061,13 +1373,26 @@ dependencies = [ "syn", ] +[[package]] +name = "serde_html_form" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d051fb33111db0e81673ed8c55db741952a19ad81dc584960c8aec836498ba5" +dependencies = [ + "form_urlencoded", + "indexmap", + "itoa 1.0.5", + "ryu", + "serde", +] + [[package]] name = "serde_json" version = "1.0.91" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877c235533714907a8c2464236f5c4b2a17262ef1bd71f38f35ea592c8da6883" dependencies = [ - "itoa", + "itoa 1.0.5", "ryu", "serde", ] @@ -1079,7 +1404,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3491c14715ca2294c4d6a88f15e84739788c1d030eed8c110436aafdaa2f3fd" dependencies = [ "form_urlencoded", - "itoa", + "itoa 1.0.5", "ryu", "serde", ] @@ -1129,6 +1454,15 @@ dependencies = [ "parking_lot 0.11.2", ] +[[package]] +name = "smallvec" +version = "0.6.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97fcaeba89edba30f044a10c6a3cc39df9c3f17d7cd829dd1446cab35f890e0" +dependencies = [ + "maybe-uninit", +] + [[package]] name = "smallvec" version = "1.10.0" @@ -1145,6 +1479,12 @@ dependencies = [ "winapi", ] +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "syn" version = "1.0.107" @@ -1191,7 +1531,7 @@ version = "0.3.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a561bf4617eebd33bca6434b988f39ed798e527f51a1e797d0ee4f61c0a38376" dependencies = [ - "itoa", + "itoa 1.0.5", "serde", "time-core", "time-macros", @@ -1242,9 +1582,21 @@ dependencies = [ "pin-project-lite", "signal-hook-registry", "socket2", + "tokio-macros", "windows-sys", ] +[[package]] +name = "tokio-macros" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d266c00fde287f55d3f1c3e96c500c362a2b8c695076ec180f27918820bc6df8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio-util" version = "0.7.4" @@ -1268,9 +1620,21 @@ dependencies = [ "cfg-if", "log", "pin-project-lite", + "tracing-attributes", "tracing-core", ] +[[package]] +name = "tracing-attributes" +version = "0.1.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4017f8f45139870ca7e672686113917c71c7a6e02d4924eda67186083c03081a" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tracing-core" version = "0.1.30" @@ -1299,6 +1663,15 @@ version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +[[package]] +name = "unicase" +version = "2.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "50f37be617794602aabbeee0be4f259dc1778fabe05e2d67ee8f79326d5cb4f6" +dependencies = [ + "version_check", +] + [[package]] name = "unicode-bidi" version = "0.3.8" diff --git a/Cargo.toml b/Cargo.toml index fd16832..d584375 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -12,8 +12,10 @@ env_logger = "0.10.0" anyhow = "1.0.68" actix-web = "4.2.1" +actix-web-lab = "0.18.9" tokio = "1.24.1" markup = "0.13.1" +chashmap = "2.2.2" sled = "0.34.7" typed-sled = "0.2.3" diff --git a/src/frontend/pages/home.rs b/src/frontend/pages/home.rs index a694c3c..bb0eb59 100644 --- a/src/frontend/pages/home.rs +++ b/src/frontend/pages/home.rs @@ -5,9 +5,9 @@ use crate::{ use actix_web::{get, web::Data, Responder}; #[get("/")] -async fn page_home(state: Data) -> impl Responder { +pub async fn page_home(state: Data) -> impl Responder { HtmlTemplate(Layout { - title: "Home - Jellything", + title: String::from("Home"), main: markup::new! { h1 { "It works!" } }, diff --git a/src/frontend/pages/layout.rs b/src/frontend/pages/layout.rs index e02336d..5654d3b 100644 --- a/src/frontend/pages/layout.rs +++ b/src/frontend/pages/layout.rs @@ -1,17 +1,19 @@ use markup::Render; markup::define! { - Layout<'a, Main: Render>(title: &'a str, main: Main) { + Layout(title: String, main: Main) { @markup::doctype() html { head { - title { @title } + title { @title " - Jellything" } link[rel="stylesheet", href="/assets/style.css"]; } body { - header { "Grain" } + nav { + h1 { "Jellything" } + + } #main { @main } - footer { span { "jellything" } } } } } diff --git a/src/frontend/pages/mod.rs b/src/frontend/pages/mod.rs index 08e0e77..6e7bd87 100644 --- a/src/frontend/pages/mod.rs +++ b/src/frontend/pages/mod.rs @@ -1,7 +1,17 @@ -use actix_web::{body::BoxBody, http::StatusCode, HttpResponseBuilder, Responder}; +use std::{error::Error, fmt::Display}; + +use actix_web::{ + body::BoxBody, + http::{ + header::{HeaderName, HeaderValue}, + StatusCode, + }, + HttpResponseBuilder, Responder, +}; pub mod home; pub mod layout; +pub mod node; struct HtmlTemplate(pub T); @@ -17,3 +27,52 @@ impl Responder for HtmlTemplate { .respond_to(req) } } + +pub struct ContentType(pub &'static str, pub T); + +impl Responder for ContentType { + type Body = T::Body; + + fn respond_to(self, req: &actix_web::HttpRequest) -> actix_web::HttpResponse { + let mut r = self.1.respond_to(req); + r.headers_mut().insert( + HeaderName::from_static("content-type"), + HeaderValue::from_static(self.0), + ); + r + } +} + +pub type MyResult = actix_web::Result; + +#[derive(Debug)] +pub struct MyError(anyhow::Error); + +impl Responder for MyError { + type Body = BoxBody; + fn respond_to(self, req: &actix_web::HttpRequest) -> actix_web::HttpResponse { + HttpResponseBuilder::new(StatusCode::BAD_REQUEST) + .body(format!("error: {}", self.0)) + .respond_to(req) + } +} +impl actix_web::error::ResponseError for MyError { + fn status_code(&self) -> StatusCode { + StatusCode::BAD_REQUEST + } +} +impl Display for MyError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + self.0.fmt(f) + } +} +impl From for MyError { + fn from(err: anyhow::Error) -> MyError { + MyError(err) + } +} +impl From for MyError { + fn from(err: std::fmt::Error) -> MyError { + MyError(anyhow::anyhow!("{err}")) + } +} diff --git a/src/frontend/pages/node.rs b/src/frontend/pages/node.rs new file mode 100644 index 0000000..c3f7791 --- /dev/null +++ b/src/frontend/pages/node.rs @@ -0,0 +1,46 @@ +use super::layout::Layout; +use crate::{ + frontend::pages::{HtmlTemplate, MyError, MyResult}, + library::{LibDirectory, LibItem, LibNode}, + AppState, +}; +use actix_web::{get, web, Responder}; +use actix_web_lab::respond::Html; +use log::debug; +use markup::Render; +use std::{ops::Deref, sync::Arc}; + +#[get("/library/{path:.*}")] +pub async fn page_library_node( + state: web::Data, + params: web::Path<(String,)>, +) -> MyResult { + debug!("request: {:?}", params.0); + let node = state.library.nested(¶ms.0)?; + let mut out = String::new(); + match node.deref() { + LibNode::Directory(dir) => Layout { + title: format!( + "{} - Library", + dir.path.file_name().unwrap().to_str().unwrap() + ), + main: Directory { dir: dir.clone() }, + } + .render(&mut out)?, + LibNode::Item(item) => Layout { + title: "".to_string(), + main: Item { item: item.clone() }, + } + .render(&mut out)?, + }; + Ok(Html(out)) +} + +markup::define! { + Directory(dir: Arc) { + h1 { @dir.data.name } + } + Item(item: Arc) { + h1 { "thats an item" } + } +} diff --git a/src/frontend/style/layout.css b/src/frontend/style/layout.css new file mode 100644 index 0000000..d6196b0 --- /dev/null +++ b/src/frontend/style/layout.css @@ -0,0 +1,35 @@ +@import url("https://s.metamuffin.org/static/font-ubuntu/include.css"); + +* { + color: white; + font-family: "Ubuntu", sans-serif; + font-weight: 300; + margin: 0px; + padding: 0px; +} + +body { + background-color: #1a1a1a; +} + +nav { + position: absolute; + top: 0px; + left: 0px; + padding: 1em; + width: 100vw; + height: 2em; + background-color: #41414144; +} + +nav h1 { + margin: 0px; + font-size: 1.5em; +} + +#main { + margin-top: 5em; + padding: 1em; + padding-left: 3em; + padding-right: 3em; +} diff --git a/src/frontend/style/master.css b/src/frontend/style/master.css deleted file mode 100644 index e69de29..0000000 diff --git a/src/frontend/style/mod.rs b/src/frontend/style/mod.rs index 180fe0e..9d0729e 100644 --- a/src/frontend/style/mod.rs +++ b/src/frontend/style/mod.rs @@ -1,2 +1,2 @@ -pub const CSS_BUNDLE: &'static str = include_str!("master.css"); +pub const CSS_BUNDLE: &'static str = include_str!("layout.css"); diff --git a/src/library.rs b/src/library.rs index 576ed77..e4c7fe6 100644 --- a/src/library.rs +++ b/src/library.rs @@ -1,23 +1,96 @@ -use anyhow::Ok; +use std::{fs::File, path::PathBuf, str::FromStr, sync::Arc}; + +use anyhow::{bail, Context, Ok}; +use chashmap::CHashMap; +use serde::{Deserialize, Serialize}; pub struct Library { - path: String, - tree: LibNode, + path: PathBuf, + cache: CHashMap, // TODO } +#[derive(Debug, Clone)] pub enum LibNode { - Directory(LibDirectory), - Item(LibItem), + Directory(Arc), + Item(Arc), +} + +#[derive(Debug, Clone)] +pub struct LibDirectory { + pub path: PathBuf, + pub child_nodes: Vec, + pub data: LibDirectoryData, +} + +#[derive(Debug, Clone)] +pub struct LibItem { + pub data: LibItemData, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct LibDirectoryData { + pub name: String, } -pub struct LibDirectory {} -pub struct LibItem {} +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct LibItemData {} impl Library { pub fn open(path: &str) -> anyhow::Result { Ok(Self { - path: path.to_string(), - tree: , + path: PathBuf::from_str(path).unwrap(), + cache: CHashMap::new(), }) } + pub fn root(&self) -> anyhow::Result> { + LibNode::from_path(self.path.clone()) + } + pub fn nested(&self, path: &str) -> anyhow::Result> { + let mut n = self.root()?; + if path == "" { + return Ok(n); + } + for seg in path.split("/") { + n = n.get_directory()?.get_child(seg)? + } + Ok(n) + } +} +impl LibDirectory { + pub fn get_child(&self, p: &str) -> anyhow::Result> { + if p.contains("..") || p.starts_with("/") { + bail!("no! dont do that.") + } + let path = self.path.join(p); + // if !path.exists() {bail!("does not exist");} + LibNode::from_path(path) + } +} +impl LibNode { + pub fn get_directory(&self) -> anyhow::Result<&LibDirectory> { + match self { + LibNode::Directory(d) => Ok(d), + LibNode::Item(_) => bail!("not a directory"), + } + } + pub fn from_path(path: PathBuf) -> anyhow::Result> { + if path.is_dir() { + let mpath = path.join("directory.json"); + let data: LibDirectoryData = + serde_json::from_reader(File::open(mpath).context("metadata missing")?)?; + let child_nodes = path.read_dir()?.map(|e| e.unwrap().path()).collect(); + Ok(LibNode::Directory(Arc::new(LibDirectory { + path, + child_nodes, + data, + })) + .into()) + } else if path.is_file() { + let mpath = path.clone().with_extension(".metadata.json"); + let data: LibItemData = serde_json::from_reader(File::open(mpath)?)?; + Ok(LibNode::Item(Arc::new(LibItem { data })).into()) + } else { + bail!("did somebody really put a fifo or socket in the library?!") + } + } } diff --git a/src/main.rs b/src/main.rs index f400920..39a4a5a 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,12 @@ -use crate::frontend::style::CSS_BUNDLE; +#![feature(box_syntax)] + +use std::fs::read_to_string; + +use crate::frontend::{pages::ContentType, style::CSS_BUNDLE}; use actix_web::{get, web, App, HttpServer, Responder}; use database::Database; -use frontend::pages::home::page_home; +use frontend::pages::{home::page_home, node::page_library_node}; +use library::Library; pub mod database; pub mod frontend; @@ -9,30 +14,33 @@ pub mod library; #[get("/assets/style.css")] async fn assets_style() -> impl Responder { - CSS_BUNDLE -} - -#[get("/{name}")] -async fn hello(name: web::Path) -> impl Responder { - format!("Hello {}!", &name) + // ContentType("text/css", CSS_BUNDLE) + ContentType( + "text/css", + read_to_string("src/frontend/style/layout.css").unwrap(), + ) } pub struct AppState { pub database: Database, + pub library: Library, } #[actix_web::main] async fn main() -> std::io::Result<()> { env_logger::init_from_env("LOG"); let db_path = std::env::var("DB_PATH").unwrap_or("data/db".to_string()); + let lib_path = std::env::var("LIB_PATH").unwrap_or("data/library".to_string()); let state = web::Data::new(AppState { - database: Database::open(&db_path).unwrap().into(), + library: Library::open(&lib_path).unwrap(), + database: Database::open(&db_path).unwrap(), }); HttpServer::new(move || { App::new() .app_data(state.clone()) .service(page_home) - .service(hello) + .service(assets_style) + .service(page_library_node) }) .bind(("127.0.0.1", 8080))? .run() -- cgit v1.2.3-70-g09d2