Compare commits

...

4 Commits

Author SHA1 Message Date
c6f43cb607 WIP 2024-06-06 16:09:27 -05:00
9df69fb1c2 Further factor out functions 2024-06-06 13:55:40 -05:00
24f69a2b6f Add hyper for tests 2024-06-06 13:41:47 -05:00
cf6f474dc6 Factor ExecutionCtx into its own fn 2024-06-06 11:48:15 -05:00
7 changed files with 299 additions and 313 deletions

View File

@ -1138,6 +1138,16 @@ dependencies = [
"pin-project-lite", "pin-project-lite",
] ]
[[package]]
name = "http-body"
version = "1.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1cac85db508abc24a2e48553ba12a996e87244a0395ce011e62b37158745d643"
dependencies = [
"bytes",
"http 1.1.0",
]
[[package]] [[package]]
name = "httparse" name = "httparse"
version = "1.8.0" version = "1.8.0"
@ -1152,9 +1162,9 @@ checksum = "df3b46402a9d5adb4c86a0cf463f42e19994e3ee891101b1841f30a545cb49a9"
[[package]] [[package]]
name = "hyper" name = "hyper"
version = "0.14.28" version = "0.14.29"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf96e135eb83a2a8ddf766e426a841d8ddd7449d5f00d34ea02b41d2f19eef80" checksum = "f361cde2f109281a220d4307746cdfd5ee3f410da58a70377762396775634b33"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-channel", "futures-channel",
@ -1162,7 +1172,7 @@ dependencies = [
"futures-util", "futures-util",
"h2", "h2",
"http 0.2.12", "http 0.2.12",
"http-body", "http-body 0.4.6",
"httparse", "httparse",
"httpdate", "httpdate",
"itoa", "itoa",
@ -1174,6 +1184,21 @@ dependencies = [
"want", "want",
] ]
[[package]]
name = "hyper"
version = "1.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe575dd17d0862a9a33781c8c4696a55c320909004a67a00fb286ba8b1bc496d"
dependencies = [
"bytes",
"http 1.1.0",
"http-body 1.0.0",
"httpdate",
"pin-project-lite",
"smallvec",
"tokio",
]
[[package]] [[package]]
name = "hyper-rustls" name = "hyper-rustls"
version = "0.24.2" version = "0.24.2"
@ -1182,7 +1207,7 @@ checksum = "ec3efd23720e2049821a693cbc7e65ea87c72f1c58ff2f9522ff332b1491e590"
dependencies = [ dependencies = [
"futures-util", "futures-util",
"http 0.2.12", "http 0.2.12",
"hyper", "hyper 0.14.29",
"rustls 0.21.12", "rustls 0.21.12",
"tokio", "tokio",
"tokio-rustls 0.24.1", "tokio-rustls 0.24.1",
@ -1434,6 +1459,15 @@ dependencies = [
"syn 2.0.66", "syn 2.0.66",
] ]
[[package]]
name = "kcl-test-server"
version = "0.1.0"
dependencies = [
"hyper 1.3.1",
"kcl-lib",
"tokio",
]
[[package]] [[package]]
name = "kittycad" name = "kittycad"
version = "0.3.3" version = "0.3.3"
@ -2095,8 +2129,8 @@ dependencies = [
"futures-util", "futures-util",
"h2", "h2",
"http 0.2.12", "http 0.2.12",
"http-body", "http-body 0.4.6",
"hyper", "hyper 0.14.29",
"hyper-rustls", "hyper-rustls",
"ipnet", "ipnet",
"js-sys", "js-sys",
@ -2165,7 +2199,7 @@ dependencies = [
"futures", "futures",
"getrandom", "getrandom",
"http 0.2.12", "http 0.2.12",
"hyper", "hyper 0.14.29",
"parking_lot 0.11.2", "parking_lot 0.11.2",
"reqwest", "reqwest",
"reqwest-middleware", "reqwest-middleware",
@ -3444,6 +3478,7 @@ dependencies = [
"console_error_panic_hook", "console_error_panic_hook",
"futures", "futures",
"gloo-utils", "gloo-utils",
"hyper 0.14.29",
"image", "image",
"js-sys", "js-sys",
"kcl-lib", "kcl-lib",

View File

@ -24,6 +24,7 @@ wasm-bindgen-futures = "0.4.42"
[dev-dependencies] [dev-dependencies]
anyhow = "1" anyhow = "1"
hyper = { version = "0.14.29", features = ["server", "http1"] }
image = { version = "0.25.1", default-features = false, features = ["png"] } image = { version = "0.25.1", default-features = false, features = ["png"] }
kittycad = { workspace = true, default-features = true } kittycad = { workspace = true, default-features = true }
pretty_assertions = "1.4.0" pretty_assertions = "1.4.0"
@ -64,6 +65,7 @@ members = [
"derive-docs", "derive-docs",
"kcl", "kcl",
"kcl-macros", "kcl-macros",
"kcl-test-server",
] ]
[workspace.dependencies] [workspace.dependencies]

View File

@ -0,0 +1,9 @@
[package]
name = "kcl-test-server"
version = "0.1.0"
edition = "2021"
[dependencies]
hyper = { version = "1.3.1", features = ["server"] }
kcl-lib = { path = "../kcl" }
tokio = { version = "1.38.0", features = ["macros", "rt-multi-thread"] }

View File

@ -0,0 +1,67 @@
use std::net::SocketAddr;
use hyper::header::CONTENT_TYPE;
use hyper::service::{make_service_fn, service_fn};
use hyper::{Body, Error, Response, Server};
use kcl_lib::executor::ExecutorContext;
use kcl_lib::settings::types::UnitLength;
use crate::new_context;
#[tokio::main]
async fn main() -> anyhow::Result<()> {
let listen_on = std::env::args().skip(1).next().unwrap();
start(listen_on).await?
}
pub async fn start(listen_on: SocketAddr) -> anyhow::Result<()> {
let state: ExecutorContext = new_context(UnitLength::Mm).await?;
// In hyper, a `MakeService` is basically your server.
// It makes a `Service` for each connection, which manages the connection.
let make_service = make_service_fn(
// This closure is run for each connection.
move |_| {
let state = state.clone();
async move {
// This is the `Service` which handles the connection.
// `service_fn` converts a function which returns a Response
// into a `Service`.
Ok::<_, Error>(service_fn(move |req| {
// Return a response.
async move {
let whole_body = hyper::body::to_bytes(req.into_body()).await?;
let Ok(kcl_src_code) = String::from_utf8(whole_body.into()) else {
return Ok(bad_request("Body was not UTF-8".to_owned()));
};
let parser = match kcl_lib::token::lexer(&kcl_src_code) {
Ok(t) => kcl_lib::parser::Parser::new(t),
Err(e) => return Ok(bad_request(format!("tokenization error: {e}"))),
};
let program = match parser.ast() {
Ok(p) => p,
Err(e) => return Ok(bad_request(format!("Parse error: {e}"))),
};
let png_bytes: Vec<u8> = todo!();
let mut resp = Response::new(Body::from(png_bytes));
resp.headers_mut().insert(CONTENT_TYPE, "image/png".parse().unwrap());
Ok::<_, Error>(resp)
}
}))
}
},
);
let server = Server::bind(&listen_on).serve(make_service);
println!("Listening on {listen_on}");
if let Err(e) = server.await {
eprintln!("Server error: {e}");
return Err(e.into());
}
Ok(())
}
fn bad_request(msg: String) -> Response<Body> {
let mut resp = Response::new(Body::from(msg));
*resp.status_mut() = hyper::StatusCode::BAD_REQUEST;
resp
}

View File

@ -11,7 +11,7 @@ use serde_json::Value as JValue;
use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange}; use tower_lsp::lsp_types::{Position as LspPosition, Range as LspRange};
use crate::{ use crate::{
ast::types::{BodyItem, FunctionExpression, KclNone, Value}, ast::types::{BodyItem, FunctionExpression, KclNone, Program, Value},
engine::EngineManager, engine::EngineManager,
errors::{KclError, KclErrorDetails}, errors::{KclError, KclErrorDetails},
fs::FileManager, fs::FileManager,
@ -975,6 +975,8 @@ impl Default for PipeInfo {
} }
/// The executor context. /// The executor context.
/// Cloning will return another handle to the same engine connection/session,
/// as this uses `Arc` under the hood.
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ExecutorContext { pub struct ExecutorContext {
pub engine: Arc<Box<dyn EngineManager>>, pub engine: Arc<Box<dyn EngineManager>>,
@ -1310,6 +1312,43 @@ impl ExecutorContext {
pub fn update_units(&mut self, units: crate::settings::types::UnitLength) { pub fn update_units(&mut self, units: crate::settings::types::UnitLength) {
self.settings.units = units; self.settings.units = units;
} }
/// Execute the program, then get a PNG screenshot.
pub async fn execute_and_prepare_snapshot(&self, program: Program) -> Result<kittycad::types::TakeSnapshot> {
let _ = self.run(program, None).await?;
// Zoom to fit.
self.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::ZoomToFit {
object_ids: Default::default(),
padding: 0.1,
},
)
.await?;
// Send a snapshot request to the engine.
let resp = self
.engine
.send_modeling_cmd(
uuid::Uuid::new_v4(),
crate::executor::SourceRange::default(),
kittycad::types::ModelingCmd::TakeSnapshot {
format: kittycad::types::ImageFormat::Png,
},
)
.await?;
let kittycad::types::OkWebSocketResponseData::Modeling {
modeling_response: kittycad::types::OkModelingCmdResponse::TakeSnapshot { data },
} = resp
else {
anyhow::bail!("Unexpected response from engine: {:?}", resp);
};
Ok(data)
}
} }
/// For each argument given, /// For each argument given,

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1 @@