summaryrefslogtreecommitdiff
path: root/rust
diff options
context:
space:
mode:
Diffstat (limited to 'rust')
-rw-r--r--rust/Cargo.lock120
-rw-r--r--rust/Cargo.toml1
-rw-r--r--rust/src/web.rs51
3 files changed, 170 insertions, 2 deletions
diff --git a/rust/Cargo.lock b/rust/Cargo.lock
index 1f35d11..0d9e14f 100644
--- a/rust/Cargo.lock
+++ b/rust/Cargo.lock
@@ -253,6 +253,55 @@ dependencies = [
]
[[package]]
+name = "anstream"
+version = "0.6.15"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "64e15c1ab1f89faffbf04a634d5e1962e9074f2741eef6d97f3c4e322426d526"
+dependencies = [
+ "anstyle",
+ "anstyle-parse",
+ "anstyle-query",
+ "anstyle-wincon",
+ "colorchoice",
+ "is_terminal_polyfill",
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle"
+version = "1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1bec1de6f59aedf83baf9ff929c98f2ad654b97c9510f4e70cf6f661d49fd5b1"
+
+[[package]]
+name = "anstyle-parse"
+version = "0.2.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eb47de1e80c2b463c735db5b217a0ddc39d612e7ac9e2e96a5aed1f57616c1cb"
+dependencies = [
+ "utf8parse",
+]
+
+[[package]]
+name = "anstyle-query"
+version = "1.1.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6d36fc52c7f6c869915e99412912f22093507da8d9e942ceaf66fe4b7c14422a"
+dependencies = [
+ "windows-sys 0.52.0",
+]
+
+[[package]]
+name = "anstyle-wincon"
+version = "3.0.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5bf74e1b6e971609db8ca7a9ce79fd5768ab6ae46441c572e46cf596f59e57f8"
+dependencies = [
+ "anstyle",
+ "windows-sys 0.52.0",
+]
+
+[[package]]
name = "async-channel"
version = "1.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -533,6 +582,52 @@ dependencies = [
]
[[package]]
+name = "clap"
+version = "4.5.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7be5744db7978a28d9df86a214130d106a89ce49644cbc4e3f0c22c3fba30615"
+dependencies = [
+ "clap_builder",
+ "clap_derive",
+]
+
+[[package]]
+name = "clap_builder"
+version = "4.5.19"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "a5fbc17d3ef8278f55b282b2a2e75ae6f6c7d4bb70ed3d0382375104bfafdb4b"
+dependencies = [
+ "anstream",
+ "anstyle",
+ "clap_lex",
+ "strsim",
+]
+
+[[package]]
+name = "clap_derive"
+version = "4.5.18"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab"
+dependencies = [
+ "heck",
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "clap_lex"
+version = "0.7.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97"
+
+[[package]]
+name = "colorchoice"
+version = "1.0.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d3fd119d74b830634cea2a0f58bbd0d54540518a14397557951e79340abc28c0"
+
+[[package]]
name = "concurrent-queue"
version = "2.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -937,6 +1032,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1e087f84d4f86bf4b218b927129862374b72199ae7d8657835f1e89000eea4fb"
[[package]]
+name = "heck"
+version = "0.5.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea"
+
+[[package]]
name = "hermit-abi"
version = "0.1.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1148,6 +1249,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ddc24109865250148c2e0f3d25d4f0f479571723792d3802153c60922a4fb708"
[[package]]
+name = "is_terminal_polyfill"
+version = "1.70.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf"
+
+[[package]]
name = "itoa"
version = "1.0.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1664,6 +1771,7 @@ dependencies = [
"actix-web",
"async-std",
"chrono",
+ "clap",
"env_logger",
"futures",
"log",
@@ -1907,6 +2015,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6980e8d7511241f8acf4aebddbb1ff938df5eebe98691418c4468d0b72a96a67"
[[package]]
+name = "strsim"
+version = "0.11.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
+
+[[package]]
name = "subtle"
version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2167,6 +2281,12 @@ dependencies = [
]
[[package]]
+name = "utf8parse"
+version = "0.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
+
+[[package]]
name = "uuid"
version = "1.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/rust/Cargo.toml b/rust/Cargo.toml
index 7635eae..01a9aa0 100644
--- a/rust/Cargo.toml
+++ b/rust/Cargo.toml
@@ -15,6 +15,7 @@ futures = "0.3.30"
async-std = "1.13.0"
reqwest = "0.12.8"
tokio = { version = "1.40.0", features = ["rt", "macros", "rt-multi-thread"]}
+clap = { version = "4.5.19", features = ["derive"] }
[dependencies.uuid]
version = "1.10.0"
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();