summaryrefslogtreecommitdiff
path: root/rust/src
diff options
context:
space:
mode:
Diffstat (limited to 'rust/src')
-rw-r--r--rust/src/web.rs51
1 files changed, 49 insertions, 2 deletions
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<Mutex<State>> = app_state.clone();
let http_state: Arc<Mutex<dyn AppState>> = 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();