use crate::simple::database::PgSharedPool; use crate::simple::http::reply_json; use warp::{Filter, Rejection, Reply}; use warp::filters::{body, method, query as params}; use warp::http::StatusCode; use serde::{Deserialize, Serialize}; use crate::app; #[derive(Deserialize)] struct PaginationOptions { pub offset: i64, pub limit: i64, } #[derive(Serialize)] struct Pagination { pub data: Vec, pub next: bool, } // add a new robot entry async fn create( shared: std::sync::Arc>, r: app::forms::GetRobot, ) -> Result { reply_json(app::robots::add_robot(shared, r).await) } // retrieve information of a single robot async fn get( shared: std::sync::Arc>, id: i64, ) -> Result { reply_json(app::robots::get_robot(shared, id).await) } // updates robot information async fn update( pool: std::sync::Arc>, id: i64, r: app::forms::GetRobot, ) -> Result { reply_json(app::robots::update_robot(pool, id, r).await) } // returns a pagination of all robots async fn get_all( pool: std::sync::Arc>, p: PaginationOptions, ) -> Result { reply_json( app::robots::get_all(pool, p.offset, p.limit) .await .map(|(r, next)| Pagination { data: r, next: next, }), ) } // will delete the requested robot async fn delete( pool: std::sync::Arc>, id: i64, ) -> Result { match app::robots::delete_robot(pool, id).await { Ok(_) => Ok(warp::reply::with_status( warp::reply(), StatusCode::NO_CONTENT, )), Err(e) => Err(warp::reject::custom(e)), } } // builds the route structure for "/robots" endpoint pub fn all( base: warp::filters::BoxedFilter<(impl Reply + 'static,)>, pool: std::sync::Arc>, ) -> warp::filters::BoxedFilter<(impl Reply,)> { // create a prefix that injects a database connection for every request // every filter is added after the prefix so it receives a database connection let prefix = warp::path!("robots").map(move || pool.clone()); base.or( // filter for creating new robots prefix .clone() // match HTTP POST method .and(method::post()) // attempts to parse the request's body as JSON .and(body::json()) // bind the handler .and_then(create), ) .or( // filter for retrieving a pagination of robots prefix .clone() // match HTTP GET method .and(method::get()) // add pagination query parameters .and(params::query()) // bind the handler .and_then(get_all), ) .boxed() } // builds the route structure for the "/robot/{id}" endpoint pub fn with_id( base: warp::filters::BoxedFilter<(impl Reply + 'static,)>, pool: std::sync::Arc>, ) -> warp::filters::BoxedFilter<(impl Reply,)> { // we create a prefix containing the id of a robot and a shared database connection // every filter is added after the prefix // so it receives a robot's id and a database connection let prefix = warp::path!("robot" / i64) .map(move |id| (pool.clone(), id)) .untuple_one(); // append the routes to the base filter base.or( // filter to get information on a robot prefix .clone() // match HTTP GET method .and(method::get()) // bind the handler .and_then(get), ) .or( // filter for updating individual robots prefix .clone() // match HTTP POST method .and(method::put()) // attempts to parse the request's body as JSON .and(body::json()) // bind the handler .and_then(update), ) .or( // filter that deletes a robot entry prefix .clone() // match HTTP DELETE method .and(method::delete()) // bind the handler .and_then(delete), ) .boxed() }