diff --git a/src/main.rs b/src/main.rs index e191aca..83fc4d0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,6 @@ use std::{ collections::HashMap, - ffi::OsString, - fs::{DirBuilder, File}, + fs::{read_to_string, DirBuilder, File}, io::{self, BufRead}, net::SocketAddr, path::PathBuf, @@ -43,21 +42,70 @@ pub enum Error { Metadata, #[error("some shit missing: {0}")] ShitMissing(String), + #[error("filesystem error")] + FS, } struct TextPaste { pub text: String, - pub meta: HashMap, + pub meta: TextMeta, +} + +struct TextMeta { + language: Option, +} + +impl TextMeta { + pub fn parse(from: &str) -> Result { + let mut map = HashMap::new(); + + from.lines() + .map(|line| line.trim()) + .filter(|line| line.len() > 0) + .map(|line| { + line.split_once(": ") + .ok_or(Error::Metadata) + .map(|(k, v)| map.insert(k.to_string(), v.to_string())) + }); + // meh, this prolly doesnt perform well but idc its only init code + Ok(Self { + language: map.remove("language"), + }) + } } struct FileMeta { file_name: String, } +impl FileMeta { + pub fn parse(from: &str) -> Result { + let map = from + .lines() + .map(|line| line.trim()) + .filter(|line| line.len() > 0) + .map(|line| line.split_once(": ").ok_or(Error::Metadata)) + .collect::, Error>>()?; + + let file_name = map.remove("file_name").ok_or(Error::Metadata)?.to_string(); + Ok(Self { file_name }) + } +} + struct UserData { - username: String, - pw_hash: String, - is_admin: bool, + pub username: String, + pub pw_hash: String, + pub is_admin: bool, +} +impl UserData { + pub fn parse(line: &str, is_admin: bool) -> Result { + let (username, pw_hash) = line.split_once(": ").ok_or(Error::Metadata)?; + Ok(Self { + username: username.trim().to_string(), + pw_hash: pw_hash.trim().to_string(), + is_admin, + }) + } } struct DataStorage { @@ -90,7 +138,7 @@ impl DataStorage { self.load_files()?; self.load_users()?; - todo!() + Ok(()) } fn ensure_folder_structure(&self) -> Result<(), Error> { @@ -114,7 +162,7 @@ impl DataStorage { for line in io::BufReader::new(f).lines() { line?; - let (id, url) = line?.split_once(": ").expect("invalid redirect format"); + let (id, url) = line?.split_once(": ").ok_or(Error::Metadata)?; self.redirects .insert(id.trim().to_string(), url.trim().to_string()); // if there's a better way to do this let me know @@ -126,8 +174,18 @@ impl DataStorage { fn load_text(&mut self) -> Result<(), Error> { for thing in std::fs::read_dir(self.base_dir.join(TEXT_DIR)).expect("fs error") { let dir_entry = thing?; // i'm so good at naming things - let f = File::open(dir_entry.path())?; - let reader = io::BufReader::new(f); + let id = dir_entry.file_name().into_string().or(Err(Error::FS))?; + let (raw_metadata, text) = read_to_string(dir_entry.path())? + .split_once("---") + .expect("invalid text format"); + let meta = TextMeta::parse(raw_metadata)?; + self.text.insert( + id, + TextPaste { + text: text.to_string(), + meta, + }, + ); } Ok(()) } @@ -135,19 +193,14 @@ impl DataStorage { fn load_files(&mut self) -> Result<(), Error> { for thing in std::fs::read_dir(self.base_dir.join(FILE_DIR)).expect("fs error") { let dir_entry = thing?; // i'm so good at naming things - let filename = dir_entry.file_name().into_string().expect("fucked up OS string"); - if filename - .ends_with(".meta") - { + let filename = dir_entry + .file_name() + .into_string() + .expect("fucked up OS string"); + if filename.ends_with(".meta") { let id = filename.trim_end_matches(".meta").to_string(); - let f = File::open(dir_entry.path())?; - let reader = io::BufReader::new(f); - let raw_metadata = HashMap::new(); - for line in reader.lines() { - let (k, v) = line?.split_once(": ").expect("invalid metadata"); - raw_metadata.insert(k.trim().to_string(), v.trim().to_string()); - } - let metadata = Self::parse_file_meta(raw_metadata)?; + let raw_metadata = read_to_string(dir_entry.path())?; + let metadata = FileMeta::parse(raw_metadata.as_str())?; self.files.insert(id, metadata); } } @@ -158,21 +211,26 @@ impl DataStorage { fn assert_all_files_present(&self) -> Result<(), Error> { let files_folder = self.base_dir.join(FILE_DIR); for (id, _) in self.files.into_iter() { - files_folder.join(id).try_exists().map_err(|_| Error::ShitMissing(id)); + files_folder + .join(id) + .try_exists() + .or(Err(Error::ShitMissing(id)))?; } Ok(()) } - fn parse_file_meta(raw: HashMap) -> Result { - let file_name = raw.get("file_name").ok_or(Error::Metadata)?.to_owned(); - Ok(FileMeta { file_name }) - } - fn load_users(&mut self) -> Result<(), Error> { - todo!() + let is_admin = true; + for line in read_to_string(self.base_dir.join(USERS_FILE))?.lines() { + if line.starts_with("---") { + is_admin = false; + break; + } + let user = UserData::parse(line, is_admin)?; + self.users.insert(user.username, user); + } + Ok(()) } - - } struct AppState {