aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormetamuffin <metamuffin@disroot.org>2023-01-10 19:52:01 +0100
committermetamuffin <metamuffin@disroot.org>2023-01-10 19:52:01 +0100
commit80e668f9cda3eb7972198dbbc65f6f72eae43c99 (patch)
tree7682be9916003edea648179911f04381a971751c /src
parent1c97c3785047d50fd5500f99457a254e0f95aefe (diff)
downloadjellything-80e668f9cda3eb7972198dbbc65f6f72eae43c99.tar
jellything-80e668f9cda3eb7972198dbbc65f6f72eae43c99.tar.bz2
jellything-80e668f9cda3eb7972198dbbc65f6f72eae43c99.tar.zst
replacing actix with rocket
Diffstat (limited to 'src')
-rw-r--r--src/frontend/pages/mod.rs11
-rw-r--r--src/frontend/pages/node.rs55
-rw-r--r--src/library.rs133
-rw-r--r--src/main.rs17
-rw-r--r--src/metadata.rs11
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(&params.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,
+}