Hey, Rust Community. I found a great start guide for building some basic endpoints but now I am trying to figure out how to parse out the struct, service, repo and main.rs. I am a total beginner with rust and coming from the OOP world. Can anybody point me in some good directions for learning api dev and maybe organizing this api I am starting? I am very excited about the possibility of writing API's using rust. Here is my starter code:
use warp::{http, Filter};
use parking_lot::RwLock;
use std::collections::HashMap;
use std::sync::Arc;
use serde::{Serialize, Deserialize};
type Items = HashMap<String, i32>;
#[derive(Debug, Deserialize, Serialize, Clone)]
struct Id {
name: String,
}
#[derive(Debug, Deserialize, Serialize, Clone)]
struct Item {
name: String,
quantity: i32,
}
#[derive(Clone)]
struct Store {
grocery_list: Arc<RwLock<Items>>
}
impl Store {
fn new() -> Self {
Store {
grocery_list: Arc::new(RwLock::new(HashMap::new())),
}
}
}
async fn update_inventory(
item: Item,
store: Store
) -> Result<impl warp::Reply, warp::Rejection> {
store.grocery_list.write().insert(item.name, item.quantity);
Ok(warp::reply::with_status(
"Added items to inventory",
http::StatusCode::CREATED,
))
}
async fn change_inventory(
item: Item,
store: Store
) -> Result<impl warp::Reply, warp::Rejection> {
let zero = 0;
let value = store.grocery_list.write().get(&item.name).unwrap_or(&zero) + item.quantity;
store.grocery_list.write().insert(item.name, value);
Ok(warp::reply::with_status(
"Added items to inventory",
http::StatusCode::CREATED,
))
}
async fn delete_inventory_item(
id: Id,
store: Store
) -> Result<impl warp::Reply, warp::Rejection> {
store.grocery_list.write().remove(&id.name);
Ok(warp::reply::with_status(
"Removed item from inventory",
http::StatusCode::OK,
))
}
async fn get_inventory(
store: Store
) -> Result<impl warp::Reply, warp::Rejection> {
let mut result = HashMap::new();
let r = store.grocery_list.read();
for (key,value) in r.iter() {
result.insert(key, value);
}
Ok(warp::reply::json(
&result
))
}
fn delete_json() -> impl Filter<Extract = (Id,), Error = warp::Rejection> + Clone {
// When accepting a body, we want a JSON body
// (and to reject huge payloads)...
warp::body::content_length_limit(1024 * 16).and(warp::body::json())
}
fn post_json() -> impl Filter<Extract = (Item,), Error = warp::Rejection> + Clone {
// When accepting a body, we want a JSON body
// (and to reject huge payloads)...
warp::body::content_length_limit(1024 * 16).and(warp::body::json())
}
#[tokio::main]
async fn main() {
let store = Store::new();
let store_filter = warp::any().map(move || store.clone());
let add_items = warp::post()
.and(warp::path("v1"))
.and(warp::path("groceries"))
.and(warp::path::end())
.and(post_json())
.and(store_filter.clone())
.and_then(update_inventory);
let get_items = warp::get()
.and(warp::path("v1"))
.and(warp::path("groceries"))
.and(warp::path::end())
.and(store_filter.clone())
.and_then(get_inventory);
let delete_item = warp::delete()
.and(warp::path("v1"))
.and(warp::path("groceries"))
.and(warp::path::end())
.and(delete_json())
.and(store_filter.clone())
.and_then(delete_inventory_item);
let update_item = warp::put()
.and(warp::path("v1"))
.and(warp::path("groceries"))
.and(warp::path::end())
.and(post_json())
.and(store_filter.clone())
.and_then(change_inventory);
let routes = add_items.or(get_items).or(delete_item).or(update_item);
warp::serve(routes)
.run(([127, 0, 0, 1], 3030))
.await;
}