use chain::{ Chain, }; use warp::{ Filter, Buf, }; use std::{ sync::Arc, }; use tokio::{ sync::{ RwLock, }, stream::{Stream,StreamExt,}, prelude::*, }; const MAX_CONTENT_LENGTH: u64 = 1024 * 16; const MAX_GEN_SIZE: usize = 256; async fn full_body(chain: &mut Chain, mut body: impl Unpin + Stream>) -> Result<(), Box> { let mut buffer = Vec::new(); while let Some(buf) = body.next().await { let mut body = buf?; while body.has_remaining() { buffer.extend_from_slice(body.bytes()); let cnt = body.bytes().len(); body.advance(cnt); } } let buffer = std::str::from_utf8(&buffer[..])?; chain.feed_str(buffer); Ok(()) } #[tokio::main] async fn main() { pretty_env_logger::init(); let chain = Arc::new(RwLock::new(Chain::new())); let chain = warp::any().map(move || Arc::clone(&chain)); let push = warp::put() .and(chain.clone()) .and(warp::path("put")) .and(warp::body::content_length_limit(MAX_CONTENT_LENGTH)) .and(warp::body::stream()) .and_then(|chain: Arc>>, buf| { async move { use std::ops::DerefMut; let res = format!("{:?}", full_body(chain.write().await.deref_mut(), buf).await); Ok::(res) } }); let read = warp::get() .and(chain.clone()) .and(warp::path("get")) .and(warp::path::param().map(|opt: usize| Some(opt)).or(warp::any().map(|| Option::::None)).unify()) .and_then(|chain: Arc>>, num: Option| { async move { let chain = chain.read().await; if chain.is_empty() { Ok(String::default()) } else { match num { Some(num) if num < MAX_GEN_SIZE => Ok(chain.str_iter_for(num).collect()), _ => Ok::(chain.generate_str()), } } } }); warp::serve(push .or(read)) .bind_with_graceful_shutdown(([127,0,0,1], 8777), async { tokio::signal::ctrl_c().await.unwrap(); }).1 .await }