diff options
author | metamuffin <metamuffin@disroot.org> | 2023-01-10 19:52:01 +0100 |
---|---|---|
committer | metamuffin <metamuffin@disroot.org> | 2023-01-10 19:52:01 +0100 |
commit | 80e668f9cda3eb7972198dbbc65f6f72eae43c99 (patch) | |
tree | 7682be9916003edea648179911f04381a971751c | |
parent | 1c97c3785047d50fd5500f99457a254e0f95aefe (diff) | |
download | jellything-80e668f9cda3eb7972198dbbc65f6f72eae43c99.tar jellything-80e668f9cda3eb7972198dbbc65f6f72eae43c99.tar.bz2 jellything-80e668f9cda3eb7972198dbbc65f6f72eae43c99.tar.zst |
replacing actix with rocket
-rw-r--r-- | src/frontend/pages/mod.rs | 11 | ||||
-rw-r--r-- | src/frontend/pages/node.rs | 55 | ||||
-rw-r--r-- | src/library.rs | 133 | ||||
-rw-r--r-- | src/main.rs | 17 | ||||
-rw-r--r-- | src/metadata.rs | 11 |
5 files changed, 121 insertions, 106 deletions
diff --git a/src/frontend/pages/mod.rs b/src/frontend/pages/mod.rs index 6145886..0e54a9a 100644 --- a/src/frontend/pages/mod.rs +++ b/src/frontend/pages/mod.rs @@ -47,18 +47,13 @@ pub type MyResult<T> = actix_web::Result<T, MyError>; #[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<Self::Body> { - 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 } + fn error_response(&self) -> actix_web::HttpResponse<BoxBody> { + HttpResponseBuilder::new(StatusCode::BAD_REQUEST).body(format!("error: {}", self.0)) + } } impl Display for MyError { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { diff --git a/src/frontend/pages/node.rs b/src/frontend/pages/node.rs index b956d3e..bb8eb6c 100644 --- a/src/frontend/pages/node.rs +++ b/src/frontend/pages/node.rs @@ -1,13 +1,10 @@ -use super::layout::Layout; use crate::{ - frontend::pages::MyResult, - library::{LibDirectory, LibItem, LibNode}, + frontend::pages::{HtmlTemplate, MyResult, layout::Layout}, + library::{Directory, Item, Node}, 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:.*}")] @@ -17,34 +14,46 @@ pub async fn page_library_node( ) -> MyResult<impl Responder> { 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", node.title()), - main: Directory { dir: dir.clone() }, - } - .render(&mut out)?, - LibNode::Item(item) => Layout { - title: "".to_string(), - main: Item { item: item.clone() }, + Ok(HtmlTemplate(markup::new! { + @match node.deref() { + Node::Directory(dir) => { + @Layout { + title: format!("{} - Library", node.title()), + main: DirectoryPage { dir: dir.clone() }, + } + } + Node::Item(item) => { + @Layout { + title: "".to_string(), + main: ItemPage { item: item.clone() }, + } + } } - .render(&mut out)?, - }; - Ok(Html(out)) + })) } markup::define! { - Directory(dir: Arc<LibDirectory>) { + DirectoryCard(dir: Arc<Directory>) { + span { a[href=&dir.identifier] { @dir.data.name } } + } + DirectoryPage(dir: Arc<Directory>) { h1 { @dir.data.name } ul.directorylisting { - @for el in &dir.child_nodes().unwrap() { + @for el in &dir.children { li { - span.title { @el.title() } + span.title { @match el.deref().to_owned() { + Node::Directory(dir) => { @DirectoryCard { dir } } + Node::Item(item) => { @ItemCard { item } } + }} } } } } - Item(item: Arc<LibItem>) { - h1 { "thats an item" } + ItemCard(item: Arc<Item>) { + span { a[href=&item.identifier] { @item.data.title } } } + ItemPage(item: Arc<Item>) { + h1 { @item.data.title } + } + } diff --git a/src/library.rs b/src/library.rs index d650733..ea0b9ed 100644 --- a/src/library.rs +++ b/src/library.rs @@ -1,119 +1,116 @@ -use std::{fs::File, path::PathBuf, str::FromStr, sync::Arc}; - -use anyhow::{bail, Context, Ok}; -use chashmap::CHashMap; -use serde::{Deserialize, Serialize}; +use crate::metadata::{DirectoryInfo, ItemInfo}; +use anyhow::{anyhow, bail, Context, Ok}; +use std::{ffi::OsStr, fs::File, path::PathBuf, sync::Arc}; pub struct Library { - path: PathBuf, - cache: CHashMap<String, LibNode>, // TODO + root: Arc<Node>, } #[derive(Debug, Clone)] -pub enum LibNode { - Directory(Arc<LibDirectory>), - Item(Arc<LibItem>), +pub enum Node { + Directory(Arc<Directory>), + Item(Arc<Item>), } #[derive(Debug, Clone)] -pub struct LibDirectory { - pub path: PathBuf, - pub child_names: Vec<String>, - pub data: LibDirectoryData, +pub struct Directory { + pub identifier: String, + pub data: DirectoryInfo, + pub children: Vec<Arc<Node>>, } #[derive(Debug, Clone)] -pub struct LibItem { - pub data: LibItemData, -} - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct LibDirectoryData { - pub name: String, -} - -#[derive(Debug, Clone, Deserialize, Serialize)] -pub struct LibItemData { - title: String, +pub struct Item { + pub identifier: String, + pub data: ItemInfo, } impl Library { pub fn open(path: &str) -> anyhow::Result<Self> { Ok(Self { - path: PathBuf::from_str(path).unwrap(), - cache: CHashMap::new(), + root: Node::from_path(path.into()).context("indexing root")?, }) } - pub fn root(&self) -> anyhow::Result<Arc<LibNode>> { - LibNode::from_path(self.path.clone()) - } - pub fn nested(&self, path: &str) -> anyhow::Result<Arc<LibNode>> { - let mut n = self.root()?; + pub fn nested(&self, path: &str) -> anyhow::Result<Arc<Node>> { + let mut n = self.root.clone(); if path == "" { return Ok(n); } for seg in path.split("/") { - n = n.get_directory()?.get_child(seg)? + n = n + .get_directory()? + .child_by_ident(seg) + .ok_or(anyhow!("does not exist"))?; } Ok(n) } } -impl LibNode { - pub fn get_directory(&self) -> anyhow::Result<&LibDirectory> { +impl Node { + pub fn get_directory(&self) -> anyhow::Result<&Directory> { match self { - LibNode::Directory(d) => Ok(d), - LibNode::Item(_) => bail!("not a directory"), + Node::Directory(d) => Ok(d), + Node::Item(_) => bail!("not a directory"), } } pub fn title(&self) -> &str { match self { - LibNode::Directory(d) => &d.data.name, - LibNode::Item(i) => &i.data.title, + Node::Directory(d) => &d.data.name, + Node::Item(i) => &i.data.title, + } + } + pub fn identifier(&self) -> &str { + match self { + Node::Directory(d) => &d.identifier, + Node::Item(i) => &i.identifier, } } - pub fn from_path(path: PathBuf) -> anyhow::Result<Arc<LibNode>> { + pub fn from_path(path: PathBuf) -> anyhow::Result<Arc<Node>> { if path.is_dir() { let mpath = path.join("directory.json"); - let data: LibDirectoryData = + let data: DirectoryInfo = serde_json::from_reader(File::open(mpath).context("metadata missing")?)?; - let child_names = path + let children = path .read_dir()? - .map(|e| e.unwrap().file_name().to_str().unwrap().to_string()) - .filter(|e| !e.ends_with(".json")) - .collect(); - Ok(LibNode::Directory(Arc::new(LibDirectory { - path, - child_names, + .map(|e| e.unwrap().path()) + .filter(|e| e.extension() != Some(OsStr::new("json"))) + .map(|e| Node::from_path(e.clone()).context(format!("loading {e:?}"))) + .into_iter() + .collect::<anyhow::Result<Vec<_>>>()?; + + Ok(Node::Directory(Arc::new(Directory { + children, data, + identifier: path.file_name().unwrap().to_str().unwrap().to_string(), })) .into()) } else if path.is_file() { let mpath = path.clone().with_extension("metadata.json"); - let data: LibItemData = - serde_json::from_reader(File::open(mpath).context("metadata missing")?) - .context("invalid metadata")?; - Ok(LibNode::Item(Arc::new(LibItem { data })).into()) + let datafile = File::open(mpath.clone()) + .context(format!("metadata missing, tried path {mpath:?}"))?; + let data: ItemInfo = serde_json::from_reader(datafile).context("invalid metadata")?; + Ok(Node::Item(Arc::new(Item { + data, + identifier: path + .with_extension("") + .file_name() + .unwrap() + .to_str() + .unwrap() + .to_string(), + })) + .into()) } else { bail!("did somebody really put a fifo or socket in the library?!") } } } -impl LibDirectory { - pub fn get_child(&self, p: &str) -> anyhow::Result<Arc<LibNode>> { - 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) - } - pub fn child_nodes(&self) -> anyhow::Result<Vec<Arc<LibNode>>> { - let mut o = vec![]; - for name in &self.child_names { - o.push(self.get_child(&name)?) - } - Ok(o) +impl Directory { + pub fn child_by_ident(&self, i: &str) -> Option<Arc<Node>> { + self.children + .iter() + .find(|e| e.identifier() == i) + .map(|e| e.to_owned()) } } diff --git a/src/main.rs b/src/main.rs index 39a4a5a..5a0b050 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,24 +1,27 @@ #![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, node::page_library_node}; use library::Library; +use std::fs::read_to_string; pub mod database; pub mod frontend; pub mod library; +pub mod metadata; #[get("/assets/style.css")] async fn assets_style() -> impl Responder { - // ContentType("text/css", CSS_BUNDLE) - ContentType( - "text/css", - read_to_string("src/frontend/style/layout.css").unwrap(), - ) + if cfg!(debug_assertions) { + ContentType( + "text/css", + read_to_string("src/frontend/style/layout.css").unwrap(), + ) + } else { + ContentType("text/css", CSS_BUNDLE.to_string()) + } } pub struct AppState { diff --git a/src/metadata.rs b/src/metadata.rs new file mode 100644 index 0000000..ff45af2 --- /dev/null +++ b/src/metadata.rs @@ -0,0 +1,11 @@ +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct DirectoryInfo { + pub name: String, +} + +#[derive(Debug, Clone, Deserialize, Serialize)] +pub struct ItemInfo { + pub title: String, +} |