#[macro_use] extern crate rocket; use std::{fs::File, io::Write}; use rocket::{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, name: &str) -> Result { for u in self.users.clone() { if u.name == name { return Ok(u) } } Err("Not Found".into()) } 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>) -> Json> { let db = db.lock().await; db.get_user(user).await.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>) -> Json> { let mut db = db.lock().await; if data.id == "random".to_string() { match db.uid_generator.new_uid() { Ok(n) => return db.new_user(data.name.clone(), n).await.into(), Err(n) => return Err(n.clone()).into(), } } else { match UID::from(data.id.clone()) { Err(n) => Err(n).into(), Ok(n) => { if db.uid_generator.is_taken(n) { return Err("UID is taken".to_string()).into(); } else { // UID is not taken match db.uid_generator.add_uid(n) { Err(n) => return Err(n).into(), Ok(n) => { return db.new_user(data.name.clone(), n).await.into(); }, } } }, } } } #[launch] fn rocket() -> _ { rocket::build().manage(Mutex::new(DB::load())).mount("/", routes![index, new_user, get_user]) }