resp-async 0.0.7

Asynchronous Redis protocol parser
Documentation
extern crate resp_async;
extern crate tokio;

use std::env;
use std::sync::Mutex;

use bytes::Bytes;
use tokio::signal;

use resp_async::error::Result;
use resp_async::{Cmd, Router, Server, State, Value};

#[derive(Default)]
struct AppState {
    history: Mutex<Vec<Value>>,
}

async fn history(State(state): State<AppState>, Cmd(cmd): Cmd) -> Value {
    if cmd.name_upper.as_ref() == b"COMMAND" {
        if let Some(Value::Bulk(arg)) = cmd.args.get(0) {
            if arg.as_ref() == b"DOCS" {
                return Value::Array(Vec::new());
            }
        }
    }

    let mut history = state.history.lock().unwrap();
    let mut entry = Vec::with_capacity(1 + cmd.args.len());
    entry.push(Value::Bulk(cmd.name));
    entry.extend(cmd.args);
    history.push(Value::Array(entry));
    Value::Array(history.clone())
}

async fn ping() -> Value {
    Value::Simple(Bytes::from_static(b"PONG"))
}

#[tokio::main]
pub async fn main() -> Result<()> {
    let addr = env::args()
        .nth(1)
        .unwrap_or_else(|| "0.0.0.0:6379".to_string());

    let app = Router::from_state(AppState::default())
        .route("HISTORY", history)
        .route("COMMAND", history)
        .route("PING", ping);

    Server::bind(&addr)
        .with_graceful_shutdown(async {
            let _ = signal::ctrl_c().await;
        })
        .serve(app)
        .await
}