diff --git a/src/api.rs b/src/api.rs index 8a79dea..eb00597 100644 --- a/src/api.rs +++ b/src/api.rs @@ -10,44 +10,50 @@ DELETE /questions/:questionId (empty body; return HTTP status code) POST /answers (www-url-encoded body; return HTTP status code) * */ -pub async fn read_question(State(store): State, Path(id): Path) -> Response { - match store.fetch(id) { +pub async fn read_question( + State(store): State>>, + Path(id): Path, +) -> Response { + match store.read().await.fetch(id) { Ok(question) => question.to_dto(id).into_response(), Err(e) => (StatusCode::NOT_FOUND, e).into_response(), } } -pub async fn read_questions(State(store): State) -> Response { - (StatusCode::OK, Json(store.fetch_all())).into_response() +pub async fn read_questions(State(store): State>>) -> Response { + (StatusCode::OK, Json(store.read().await.fetch_all())).into_response() } pub async fn create_question( - State(store): State, + State(store): State>>, Json(question_dto): Json, ) -> Response { //Normally, the server should generate the id, user provided id's (and the whole request) should be rejected. //QuestionDTO id then would be an option, but that makes to/from entity conversion more tricky.. todo let (id, question) = question_dto.to_entity(); - match store.add(id, question) { + match store.write().await.add(id, question) { Ok(question) => (StatusCode::CREATED, Json(&question.to_dto(id))).into_response(), Err(e) => (StatusCode::CONFLICT, e).into_response(), } } pub async fn update_question( - State(store): State, + State(store): State>>, Json(question_dto): Json, ) -> Response { let (id, question) = question_dto.to_entity(); - match store.update(id, question) { + match store.write().await.update(id, question) { Ok(question) => question.to_dto(id).into_response(), Err(e) => (StatusCode::NOT_FOUND, e).into_response(), } } -pub async fn delete_question(State(store): State, Path(id): Path) -> Response { - match store.remove(id) { +pub async fn delete_question( + State(store): State>>, + Path(id): Path, +) -> Response { + match store.write().await.remove(id) { Ok(question) => question.to_dto(id).into_response(), Err(e) => (StatusCode::NOT_FOUND, e).into_response(), } } -pub async fn create_answer(State(_store): State /*TODO */) -> Response { +pub async fn create_answer(State(_store): State>> /*TODO */) -> Response { todo!() } diff --git a/src/main.rs b/src/main.rs index e7fc853..a57d5c0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -12,8 +12,9 @@ use axum::{ use serde::{Deserialize, Serialize}; use std::collections::HashMap; use std::net::SocketAddr; -//use std::sync::Arc; -//use tokio::sync::{self,RwLock}; +use std::sync::Arc; +use store::Store; +use tokio::sync::RwLock; async fn handle() -> Response { (StatusCode::OK, "Visiting the root").into_response() @@ -25,21 +26,21 @@ async fn handler_404() -> Response { #[tokio::main] async fn main() { - let store = store::Store::new(); + let store: Arc> = Arc::new(RwLock::new(store::Store::new())); let ip: SocketAddr = SocketAddr::new([127, 0, 0, 1].into(), 3000); let listener: tokio::net::TcpListener = tokio::net::TcpListener::bind(ip).await.unwrap(); - let apis: Router = Router::new() + let apis = Router::new() .route("/question/:id", get(api::read_question)) .route("/questions", get(api::read_questions)) .route("/question", post(api::create_question)) .route("/question/:id", put(api::update_question)) .route("/question/:id", delete(api::delete_question)) .route("/answers", post(api::create_answer)) - //.nest(path, router) .with_state(store) .fallback(handler_404); - let app: Router = Router::new().route("/", get(handle)).merge(apis); + + let app = Router::new().route("/", get(handle)).merge(apis); axum::serve(listener, app).await.unwrap(); } diff --git a/src/store.rs b/src/store.rs index 64e0b4c..1b2e20e 100644 --- a/src/store.rs +++ b/src/store.rs @@ -15,14 +15,15 @@ impl Store { } fn init() -> HashMap { let file = include_str!("./questions.json"); - let a: Vec = serde_json::from_str(file).expect("can't read questions.json"); - println!("init"); - a.into_iter() + let questions_vec: Vec = + serde_json::from_str(file).expect("can't read questions.json"); + questions_vec + .into_iter() .map(|question_dto: QuestionDTO| question_dto.to_entity()) .collect() } - pub fn add(mut self, id: u8, question: Question) -> Result { + pub fn add(&mut self, id: u8, question: Question) -> Result { if self.questions.contains_key(&id) { return Err(format!("Question with id {} already exists", id)); } @@ -31,22 +32,22 @@ impl Store { _ => Err("Server Error".to_string()), } } - pub fn remove(mut self, id: u8) -> Result { + pub fn remove(&mut self, id: u8) -> Result { match self.questions.remove(&id) { Some(question) => Ok(question), None => Err(format!("Question with id {} does not exist", id)), } } - pub fn fetch(self, id: u8) -> Result { + pub fn fetch(&self, id: u8) -> Result { match self.questions.get(&id) { Some(question) => Ok(question.clone()), None => Err(format!("Question with id {} does not exists", id)), } } - pub fn fetch_all(self) -> Vec { + pub fn fetch_all(&self) -> Vec { self.questions.values().cloned().collect() } - pub fn update(mut self, id: u8, question: Question) -> Result { + pub fn update(&mut self, id: u8, question: Question) -> Result { if !self.questions.contains_key(&id) { return Err(format!("Question with id {} does not exists", id)); }