#[macro_use] extern crate rocket; use std::{fs::File, io::Write, vec}; use rocket::{http::Status, serde::json::Json, State}; use serde::{Deserialize, Serialize}; mod uid; use tokio::sync::Mutex; use uid::UID; #[derive(Debug, Serialize, Deserialize, Clone, Copy)] enum Color { White, Red, Blue, Green, Yellow, } #[derive(Debug, Serialize, Deserialize, Clone)] struct Token { color: Color, amount: usize, } impl Token { pub fn new(color: Color, amount: usize) -> Token { Token { color, amount } } } #[derive(Debug, Serialize, Deserialize, Clone)] struct User { name: String, id: UID, tokovec: Vec } impl User { pub fn new(name: String, id: UID) -> User { let base_tokens = vec![ Token::new(Color::White, 2), Token::new(Color::Red, 2), Token::new(Color::Blue, 2), Token::new(Color::Green, 2), Token::new(Color::Yellow, 2), ]; User { name: name, id: id, tokovec: base_tokens } } } const DBSAVE: &str = "db.json"; #[derive(Serialize, Deserialize)] struct DB { uid_generator: uid::Generator, users: Vec, } impl DB { async fn save(&self) -> Result<(), String> { let mut f = match File::create(DBSAVE) { Ok(n) => n, Err(n) => { match n.kind() { std::io::ErrorKind::PermissionDenied => panic!("{}: Permission Denied", DBSAVE), n => return Err(n.to_string()), } }, }; let s = match serde_json::to_string(self) { Ok(n) => n, Err(n) => return Err(n.to_string()), }; match f.write(s.as_bytes()) { Ok(_) => return Ok(()), Err(n) => return Err(n.to_string()), }; } pub fn load() -> Self { match File::open(DBSAVE) { Ok(n) => { match serde_json::from_reader(n) { Ok(n) => n, Err(n) => panic!("{}", n), } }, Err(n) => match n.kind() { std::io::ErrorKind::PermissionDenied => panic!("{}: Permission Denied", DBSAVE), _ => DB::new(), }, } } pub fn new() -> Self { DB { uid_generator: uid::Generator::new(), users: vec![] } } async fn get_user(&self, id: &str) -> Result { match UID::from(id.to_string()) { Ok(n) => { for u in self.users.clone() { if u.id == n { return Ok(u) } } }, Err(_) => (), } Err("Not Found".into()) } async fn get_user_by_name(&self, name: &str) -> Result, String> { let mut vec = vec![]; for u in self.users.clone() { if u.name == name { vec.push(u) } } if vec.len() == 0 { Err("Not Found".into()) } else { return Ok(vec) } } async fn new_user(&mut self, name: String, id: UID) -> Result<(), String> { let user = User::new(name, id); self.users.push(user); self.save().await } } #[get("/")] async fn index() -> &'static str { "This is a POKO server" } #[get("/user/")] async fn get_user(user: &str, db: &State>) -> (Status, Result, Json>) { let db = db.lock().await; match db.get_user(user).await { Ok(n) => (Status::Ok, Ok(n.into())), Err(n) => (Status::NotFound, Err(n.into())) } } #[get("/user/by_name/")] async fn get_users_by_name(user: &str, db: &State>) -> (Status, Result>, Json>) { let db = db.lock().await; match db.get_user_by_name(user).await { Ok(n) => (Status::Ok, Ok(n.into())), Err(n) => (Status::NotFound, Err(n.into())) } } fn default_id() -> String { "random".into() } #[derive(Deserialize)] struct UserForm { name: String, #[serde(default = "default_id")] id: String, } #[post("/user", data="", format="json")] async fn new_user(data: Json, db: &State>) -> (Status, Result<(), Json>) { let mut db = db.lock().await; let id; if data.id == "random".to_string() { match db.uid_generator.new_uid() { // Gotten a new UID to make a new user with Ok(n) => id = Some(n), // Did not get a new UID Err(n) => return (Status::InternalServerError, Err(n.clone().into())), }; } else { match UID::from(data.id.clone()) { // Could not make UID from input Err(n) => return (Status::BadRequest, Err(n.into())), // Made a UID Ok(n) => { if db.uid_generator.is_taken(n) { // UID is taken return (Status::BadRequest, Err("UID is taken".to_string().into())); } else { // UID is not taken match db.uid_generator.add_uid(n) { // Could not add UID for some reason Err(n) => return (Status::InternalServerError, Err(n.into())), // Made Ok(n) => id = Some(n), }; } }, }; } match id { None => return (Status::InternalServerError, Err("".to_string().into())), Some(n) => { match db.new_user(data.name.clone(), n).await { // User has been created Ok(_) => return (Status::Created, Ok(())), // Could not create user Err(n) => return (Status::InternalServerError, Err(n.into())), } } } } #[launch] fn rocket() -> _ { rocket::build().manage(Mutex::new(DB::load())).mount("/", routes![index, new_user, get_user, get_users_by_name]) }