From d96f415a2cfb55715c095cc9c2775b1413e06203 Mon Sep 17 00:00:00 2001 From: Arnaud Bailly Date: Sat, 5 Oct 2024 15:04:10 +0200 Subject: Server can also evaluate expressions --- rust/src/web.rs | 51 +++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 49 insertions(+), 2 deletions(-) (limited to 'rust/src/web.rs') diff --git a/rust/src/web.rs b/rust/src/web.rs index 94b01cb..b48900e 100644 --- a/rust/src/web.rs +++ b/rust/src/web.rs @@ -2,6 +2,7 @@ use actix_web::{ get, http::header::ContentType, middleware::Logger, post, web, App, HttpResponse, HttpServer, Responder, }; +use clap::Parser; use futures::try_join; use futures::{future::join_all, lock::Mutex}; use log::info; @@ -90,8 +91,33 @@ async fn register( } } +#[post("/eval")] +async fn eval(input: String) -> impl Responder { + let mut env = Environment::new(); + match parse(&input).first() { + Some(expr) => { + let output = eval_whnf(expr, &mut env); + HttpResponse::Ok().body(format!("{}", output)) + } + None => HttpResponse::BadRequest().finish(), + } +} + +#[derive(Parser, Debug)] +struct Options { + /// The port to listen on + /// Defaults to 8080 + #[arg(short, long, default_value_t = 8080)] + port: u16, + /// The host to bind the server to + /// Defaults to 127.0.0.1 + #[arg(long, default_value = "127.0.0.1")] + host: String, +} + #[tokio::main] async fn main() -> std::io::Result<()> { + let options = Options::parse(); let app_state = Arc::new(Mutex::new(State::new())); let send_state: Arc> = app_state.clone(); let http_state: Arc> = app_state; @@ -103,8 +129,9 @@ async fn main() -> std::io::Result<()> { .wrap(Logger::default()) .app_data(web::Data::new(http_state.clone())) .service(register) + .service(eval) }) - .bind(("127.0.0.1", 8080))? + .bind((options.host, options.port))? .run() .await } @@ -134,6 +161,7 @@ async fn send_test(grade: u8, url: &String) -> Result<(), String> { info!("Sending {} to {}", input, url); let response = reqwest::Client::new() .post(url) + .header("content-type", "text/plain") .body(format!("{}", input)) .send() .await; @@ -141,7 +169,7 @@ async fn send_test(grade: u8, url: &String) -> Result<(), String> { Ok(response) => { let body = response.text().await.unwrap(); let vals = parse(&body); - // FIXME + // FIXME: should be able to handle multiple values let result = eval_whnf(vals.first().unwrap(), &mut env); info!("Received {} from {}", body, url); if result == output { @@ -256,6 +284,25 @@ mod app_tests { ); } + #[actix_web::test] + async fn post_expression_returns_evaluation() { + let app = test::init_service(App::new().wrap(Logger::default()).service(eval)).await; + + let req = test::TestRequest::post() + .uri("/eval") + .set_payload("((lam (x y) x) 1 2)") + .insert_header(ContentType::plaintext()) + .to_request(); + + let resp = test::call_service(&app, req).await; + + assert!(resp.status().is_success()); + + let body = resp.into_body(); + let bytes = body::to_bytes(body).await.unwrap(); + assert_eq!(bytes, "1".to_string().into_bytes()); + } + #[test] async fn app_does_not_register_same_url_twice() { let mut app_state = State::new(); -- cgit v1.2.3