diff --git a/src/main.rs b/src/main.rs index c4cdde0..49c7c71 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,18 +12,21 @@ use serde_json::Value; use rocket_contrib::serve::StaticFiles; use rocket_contrib::templates::Template; -mod store; mod session; +mod store; -use crate::store::form::{render_card_fields, render_empty_fields, RenderedCard, RenderedField, MapFromForm, collect_card_form}; +use crate::store::form::{ + collect_card_form, render_card_fields, render_empty_fields, MapFromForm, RenderedCard, + RenderedField, +}; use crate::store::Store; use parking_lot::RwLock; +use crate::session::{Session, SessionID, SessionStore}; use rocket::request::Form; use rocket::response::Redirect; -use rocket::{State, Request}; +use rocket::{Request, State}; use std::env; -use crate::session::{SessionID, SessionStore, Session}; #[derive(Serialize, Debug)] pub struct ListContext<'a> { @@ -31,7 +34,7 @@ pub struct ListContext<'a> { pub cards: Vec>, pub page: usize, pub pages: usize, - pub count : usize, + pub count: usize, } const PER_PAGE: usize = 20; // TODO configurable @@ -51,14 +54,10 @@ fn find_page_with_card(store: &Store, card_id: usize) -> Option { } #[get("/?")] -fn route_index( - store: State>, - session : Session, - page: Option -) -> Template { +fn route_index(store: State>, session: Session, page: Option) -> Template { let rg = store.read(); - let mut count : usize = session.get_or_default("foo.bar.count"); + let mut count: usize = session.get_or_default("foo.bar.count"); count += 1; session.set("foo.bar.count", count); diff --git a/src/session.rs b/src/session.rs index 260cbd6..c503d2a 100644 --- a/src/session.rs +++ b/src/session.rs @@ -1,18 +1,21 @@ -use rocket::request::FromRequest; -use rocket::{Outcome, Request, State, http::{Status, Cookies, Cookie}, Response, Data, Rocket}; -use std::ops::{Deref, DerefMut}; -use std::collections::HashMap; +use json_dotpath::DotPaths; use parking_lot::{Mutex, MutexGuard, RwLock, RwLockReadGuard, RwLockWriteGuard}; -use serde_json::{Value, Map}; -use rocket::fairing::{self, Fairing, Info}; use rand::Rng; -use std::borrow::Cow; -use serde::{Deserialize, Serialize}; -use serde::de::DeserializeOwned; -use json_dotpath::DotPaths; +use rocket::fairing::{self, Fairing, Info}; +use rocket::request::FromRequest; use rocket::response::ResponseBuilder; +use rocket::{ + http::{Cookie, Cookies, Status}, + Data, Outcome, Request, Response, Rocket, State, +}; +use serde::de::DeserializeOwned; +use serde::{Deserialize, Serialize}; +use serde_json::{Map, Value}; +use std::borrow::Cow; +use std::collections::HashMap; +use std::ops::{Deref, DerefMut}; -const SESSION_ID : &'static str = "SESSID"; +const SESSION_ID: &'static str = "SESSID"; type SessionsMap = HashMap; @@ -41,10 +44,12 @@ impl<'a, 'r> FromRequest<'a, 'r> for &'a SessionID { SessionID(cookie.value().to_string()) // FIXME avoid cloning } else { println!("new id"); - SessionID(rand::thread_rng() - .sample_iter(&rand::distributions::Alphanumeric) - .take(16) - .collect()) + SessionID( + rand::thread_rng() + .sample_iter(&rand::distributions::Alphanumeric) + .take(16) + .collect(), + ) } })) } @@ -53,7 +58,7 @@ impl<'a, 'r> FromRequest<'a, 'r> for &'a SessionID { #[derive(Debug)] pub struct Session<'a> { store: State<'a, SessionStore>, - id : &'a SessionID, + id: &'a SessionID, } impl<'a, 'r> FromRequest<'a, 'r> for Session<'a> { @@ -65,13 +70,15 @@ impl<'a, 'r> FromRequest<'a, 'r> for Session<'a> { if let Some(cookie) = request.cookies().get(SESSION_ID) { SessionID(cookie.value().to_string()) } else { - SessionID(rand::thread_rng() - .sample_iter(&rand::distributions::Alphanumeric) - .take(16) - .collect()) + SessionID( + rand::thread_rng() + .sample_iter(&rand::distributions::Alphanumeric) + .take(16) + .collect(), + ) } }), - store: request.guard().unwrap() + store: request.guard().unwrap(), }) } } @@ -81,7 +88,7 @@ impl<'a> Session<'a> { SessionFairing } - pub fn get(&self, path : &str) -> Option { + pub fn get(&self, path: &str) -> Option { let rg = self.store.inner.read(); if let Some(ses) = rg.get(&self.id.0) { ses.data.dot_get(path) @@ -90,19 +97,19 @@ impl<'a> Session<'a> { } } - pub fn get_or(&self, path : &str, def : T) -> T { + pub fn get_or(&self, path: &str, def: T) -> T { self.get(path).unwrap_or(def) } - pub fn get_or_else T>(&self, path : &str, def : F) -> T { + pub fn get_or_else T>(&self, path: &str, def: F) -> T { self.get(path).unwrap_or_else(def) } - pub fn get_or_default(&self, path : &str) -> T { + pub fn get_or_default(&self, path: &str) -> T { self.get(path).unwrap_or_default() } - pub fn take(&self, path : &str) -> Option { + pub fn take(&self, path: &str) -> Option { let mut wg = self.store.inner.write(); if let Some(ses) = wg.get_mut(&self.id.0) { ses.data.dot_take(path) @@ -111,7 +118,7 @@ impl<'a> Session<'a> { } } - pub fn replace(&self, path : &str, new : N) -> Option { + pub fn replace(&self, path: &str, new: N) -> Option { let mut wg = self.store.inner.write(); if let Some(ses) = wg.get_mut(&self.id.0) { ses.data.dot_replace(path, new) @@ -120,20 +127,18 @@ impl<'a> Session<'a> { } } - pub fn set(&self, path : &str, value : T) { + pub fn set(&self, path: &str, value: T) { let mut wg = self.store.inner.write(); if let Some(ses) = wg.get_mut(&self.id.0) { ses.data.dot_set(path, value); } else { let mut map = Map::new(); map.dot_set(path, value); - wg.insert(self.id.0.clone(), SessionInstance { - data : map, - }); + wg.insert(self.id.0.clone(), SessionInstance { data: map }); } } - pub fn remove(&self, path : &str) { + pub fn remove(&self, path: &str) { let mut wg = self.store.inner.write(); if let Some(ses) = wg.get_mut(&self.id.0) { ses.data.dot_remove(path); @@ -148,7 +153,7 @@ impl Fairing for SessionFairing { fn info(&self) -> Info { Info { name: "Session Fairing", - kind: fairing::Kind::Attach | fairing::Kind::Response + kind: fairing::Kind::Attach | fairing::Kind::Response, } } @@ -157,9 +162,7 @@ impl Fairing for SessionFairing { } fn on_response<'r>(&self, request: &'r Request, response: &mut Response) { - let session = request.local_cache(|| { - SessionID("".to_string()) - }); + let session = request.local_cache(|| SessionID("".to_string())); if !session.0.is_empty() { response.adjoin_header(Cookie::build(SESSION_ID, session.0.clone()).finish()); diff --git a/src/store/form.rs b/src/store/form.rs index 6532ed7..fb7f5d7 100644 --- a/src/store/form.rs +++ b/src/store/form.rs @@ -4,8 +4,8 @@ use serde_json::Value; use std::borrow::Cow; use std::collections::BTreeSet; -use lazy_static::lazy_static; use indexmap::map::IndexMap; +use lazy_static::lazy_static; use rocket::request::{FormItems, FromForm}; lazy_static! { @@ -194,7 +194,6 @@ pub fn render_card_fields<'a>( .collect() } - #[derive(Default)] pub struct MapFromForm { pub data: IndexMap, diff --git a/src/store/mod.rs b/src/store/mod.rs index ba5a93e..d6ad4a7 100644 --- a/src/store/mod.rs +++ b/src/store/mod.rs @@ -1,13 +1,13 @@ -use crate::store::model::{Model, FieldKind}; +use crate::store::model::{FieldKind, Model}; use indexmap::map::IndexMap; +use json_dotpath::DotPaths; use serde::Serialize; use serde_json::Value; use std::collections::HashMap; +use std::collections::{BTreeMap, BTreeSet}; use std::fs::{File, OpenOptions}; use std::io::{Read, Write}; use std::path::{Path, PathBuf}; -use std::collections::{BTreeMap, BTreeSet}; -use json_dotpath::DotPaths; pub mod form; pub mod model; @@ -17,7 +17,7 @@ pub mod model; pub struct Store { path: PathBuf, pub model: Model, - freeform_fields : FreeformFieldsOfInterest, + freeform_fields: FreeformFieldsOfInterest, pub data: Cards, pub index: Indexes, } @@ -68,10 +68,14 @@ impl Store { /// Handle a data change. /// If a card was modified, selectively update the tags index - fn on_change(&mut self, changed_card : Option) { + fn on_change(&mut self, changed_card: Option) { if let Some(id) = changed_card { // this needs to be so ugly because of lifetimes - we need a mutable reference to the index - Self::index_card(&mut self.index, &self.freeform_fields, self.data.cards.get(&id).unwrap()); + Self::index_card( + &mut self.index, + &self.freeform_fields, + self.data.cards.get(&id).unwrap(), + ); } self.persist(); @@ -123,22 +127,22 @@ impl Store { /// Get a list of free_tags and free_enum fields /// /// Returns (free_tags, free_enums), where both members are vecs of (field_key, index_group) - fn get_fields_for_freeform_indexes(model : &Model) -> FreeformFieldsOfInterest { + fn get_fields_for_freeform_indexes(model: &Model) -> FreeformFieldsOfInterest { // tuples (key, group) - let mut free_enum_fields : Vec = vec![]; - let mut free_tag_fields : Vec = vec![]; + let mut free_enum_fields: Vec = vec![]; + let mut free_tag_fields: Vec = vec![]; for (key, field) in &model.fields { match &field.kind { FieldKind::FreeEnum { enum_group } => { let enum_group = enum_group.as_ref().unwrap_or(key); free_enum_fields.push(KeyAndGroup(key.to_string(), enum_group.to_string())); - }, + } FieldKind::FreeTags { tag_group } => { let tag_group = tag_group.as_ref().unwrap_or(key); free_tag_fields.push(KeyAndGroup(key.to_string(), tag_group.to_string())); - }, - _ => {}, + } + _ => {} } } @@ -149,7 +153,11 @@ impl Store { } /// This is an associated function to split the lifetimes - fn index_card<'a>(index : &mut Indexes, freeform_fields : &FreeformFieldsOfInterest, card : &'a Value) { + fn index_card<'a>( + index: &mut Indexes, + freeform_fields: &FreeformFieldsOfInterest, + card: &'a Value, + ) { for KeyAndGroup(key, group) in &freeform_fields.free_enum_fields { if !index.free_enums.contains_key(key.as_str()) { index.free_enums.insert(key.to_string(), Default::default()); @@ -194,14 +202,15 @@ struct FreeformFieldsOfInterest { pub free_enum_fields: Vec, } -fn write_file(path : impl AsRef, bytes : &[u8]) { +fn write_file(path: impl AsRef, bytes: &[u8]) { let mut file = OpenOptions::new() - .write(true).create(true).truncate(true) + .write(true) + .create(true) + .truncate(true) .open(path) .expect("Error opening data file for writing."); - file.write(bytes) - .expect("Error write data file"); + file.write(bytes).expect("Error write data file"); } fn load_file(path: impl AsRef) -> String {