tide 0.0.5

WIP modular web framework
Documentation
#![feature(async_await, futures_api)]

#[macro_use]
extern crate serde_derive;

use http::status::StatusCode;
use std::sync::{Arc, Mutex};
use tide::{body, head, App, AppData};

#[derive(Clone, Default)]
struct Database {
    contents: Arc<Mutex<Vec<Message>>>,
}

#[derive(Serialize, Deserialize, Clone)]
struct Message {
    author: Option<String>,
    contents: String,
}

impl Database {
    fn insert(&mut self, msg: Message) -> usize {
        let mut table = self.contents.lock().unwrap();
        table.push(msg);
        table.len() - 1
    }

    fn get(&mut self, id: usize) -> Option<Message> {
        self.contents.lock().unwrap().get(id).cloned()
    }

    fn set(&mut self, id: usize, msg: Message) -> bool {
        let mut table = self.contents.lock().unwrap();

        if let Some(old_msg) = table.get_mut(id) {
            *old_msg = msg;
            true
        } else {
            false
        }
    }
}

async fn new_message(mut db: AppData<Database>, msg: body::Json<Message>) -> String {
    db.insert(msg.clone()).to_string()
}

async fn set_message(
    mut db: AppData<Database>,
    id: head::Path<usize>,
    msg: body::Json<Message>,
) -> Result<(), StatusCode> {
    if db.set(*id, msg.clone()) {
        Ok(())
    } else {
        Err(StatusCode::NOT_FOUND)
    }
}

async fn get_message(
    mut db: AppData<Database>,
    id: head::Path<usize>,
) -> Result<body::Json<Message>, StatusCode> {
    if let Some(msg) = db.get(*id) {
        Ok(body::Json(msg))
    } else {
        Err(StatusCode::NOT_FOUND)
    }
}

fn main() {
    let mut app = App::new(Database::default());

    app.at("/message").post(new_message);
    app.at("/message/{}").get(get_message);
    app.at("/message/{}").post(set_message);

    app.serve();
}