Kcl updates for snapshot stuff for cli (#350)
* updates for snapshot file Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
6
src/wasm-lib/Cargo.lock
generated
6
src/wasm-lib/Cargo.lock
generated
@ -947,7 +947,7 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bson",
|
"bson",
|
||||||
@ -975,9 +975,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "kittycad"
|
name = "kittycad"
|
||||||
version = "0.2.21"
|
version = "0.2.22"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "dfeb41d39852f5755cd3f2d1c06059839f268cbc5d0577c2d6a667c6ad5abdcf"
|
checksum = "0247f7acbe36141604ad02b796b596fe0392fb86dd82550eb2f4855b2a493344"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"base64 0.21.2",
|
"base64 0.21.2",
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
[package]
|
[package]
|
||||||
name = "kcl-lib"
|
name = "kcl-lib"
|
||||||
description = "KittyCAD Language"
|
description = "KittyCAD Language"
|
||||||
version = "0.1.2"
|
version = "0.1.3"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
license = "MIT"
|
license = "MIT"
|
||||||
|
|
||||||
|
@ -15,6 +15,7 @@ pub struct EngineConnection {
|
|||||||
tcp_write: futures::stream::SplitSink<tokio_tungstenite::WebSocketStream<reqwest::Upgraded>, WsMsg>,
|
tcp_write: futures::stream::SplitSink<tokio_tungstenite::WebSocketStream<reqwest::Upgraded>, WsMsg>,
|
||||||
tcp_read_handle: tokio::task::JoinHandle<Result<()>>,
|
tcp_read_handle: tokio::task::JoinHandle<Result<()>>,
|
||||||
export_notifier: Arc<tokio::sync::Notify>,
|
export_notifier: Arc<tokio::sync::Notify>,
|
||||||
|
snapshot_notifier: Arc<tokio::sync::Notify>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Drop for EngineConnection {
|
impl Drop for EngineConnection {
|
||||||
@ -41,7 +42,7 @@ impl TcpRead {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl EngineConnection {
|
impl EngineConnection {
|
||||||
pub async fn new(ws: reqwest::Upgraded, export_dir: &str) -> Result<EngineConnection> {
|
pub async fn new(ws: reqwest::Upgraded, export_dir: &str, snapshot_file: &str) -> Result<EngineConnection> {
|
||||||
// Make sure the export directory exists and that it is a directory.
|
// Make sure the export directory exists and that it is a directory.
|
||||||
let export_dir = std::path::Path::new(export_dir).to_owned();
|
let export_dir = std::path::Path::new(export_dir).to_owned();
|
||||||
if !export_dir.exists() {
|
if !export_dir.exists() {
|
||||||
@ -66,6 +67,11 @@ impl EngineConnection {
|
|||||||
let export_notifier = Arc::new(tokio::sync::Notify::new());
|
let export_notifier = Arc::new(tokio::sync::Notify::new());
|
||||||
let export_notifier_clone = export_notifier.clone();
|
let export_notifier_clone = export_notifier.clone();
|
||||||
|
|
||||||
|
let snapshot_notifier = Arc::new(tokio::sync::Notify::new());
|
||||||
|
let snapshot_notifier_clone = snapshot_notifier.clone();
|
||||||
|
|
||||||
|
let snapshot_file = snapshot_file.to_owned();
|
||||||
|
|
||||||
let tcp_read_handle = tokio::spawn(async move {
|
let tcp_read_handle = tokio::spawn(async move {
|
||||||
// Get Websocket messages from API server
|
// Get Websocket messages from API server
|
||||||
loop {
|
loop {
|
||||||
@ -90,7 +96,20 @@ impl EngineConnection {
|
|||||||
OkWebSocketResponseData::TrickleIce { candidate } => {
|
OkWebSocketResponseData::TrickleIce { candidate } => {
|
||||||
println!("got trickle ice: {:?}", candidate);
|
println!("got trickle ice: {:?}", candidate);
|
||||||
}
|
}
|
||||||
OkWebSocketResponseData::Modeling { .. } => {}
|
OkWebSocketResponseData::Modeling { modeling_response } => {
|
||||||
|
if let kittycad::types::OkModelingCmdResponse::TakeSnapshot { data } =
|
||||||
|
modeling_response
|
||||||
|
{
|
||||||
|
if snapshot_file.is_empty() {
|
||||||
|
println!("Got snapshot, but no snapshot file specified.");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Save the snapshot locally.
|
||||||
|
std::fs::write(&snapshot_file, data.contents)?;
|
||||||
|
snapshot_notifier.notify_one();
|
||||||
|
}
|
||||||
|
}
|
||||||
OkWebSocketResponseData::Export { files } => {
|
OkWebSocketResponseData::Export { files } => {
|
||||||
// Save the files to our export directory.
|
// Save the files to our export directory.
|
||||||
for file in files {
|
for file in files {
|
||||||
@ -118,13 +137,18 @@ impl EngineConnection {
|
|||||||
tcp_write,
|
tcp_write,
|
||||||
tcp_read_handle,
|
tcp_read_handle,
|
||||||
export_notifier: export_notifier_clone,
|
export_notifier: export_notifier_clone,
|
||||||
|
snapshot_notifier: snapshot_notifier_clone,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn wait_for_files(&self) {
|
pub async fn wait_for_export(&self) {
|
||||||
self.export_notifier.notified().await;
|
self.export_notifier.notified().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn wait_for_snapshot(&self) {
|
||||||
|
self.snapshot_notifier.notified().await;
|
||||||
|
}
|
||||||
|
|
||||||
pub async fn tcp_send(&mut self, msg: WebSocketRequest) -> Result<()> {
|
pub async fn tcp_send(&mut self, msg: WebSocketRequest) -> Result<()> {
|
||||||
let msg = serde_json::to_string(&msg)?;
|
let msg = serde_json::to_string(&msg)?;
|
||||||
self.tcp_write.send(WsMsg::Text(msg)).await?;
|
self.tcp_write.send(WsMsg::Text(msg)).await?;
|
||||||
@ -149,60 +173,3 @@ impl EngineConnection {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
|
||||||
mod tests {
|
|
||||||
use super::*;
|
|
||||||
use crate::executor::{execute, BodyType, ProgramMemory, SourceRange};
|
|
||||||
|
|
||||||
pub async fn parse_execute_export(code: &str) -> Result<()> {
|
|
||||||
let tokens = crate::tokeniser::lexer(code);
|
|
||||||
let export_dir_str = "/tmp/";
|
|
||||||
let program = crate::parser::abstract_syntax_tree(&tokens)?;
|
|
||||||
let mut mem: ProgramMemory = Default::default();
|
|
||||||
let mut engine = EngineConnection::new(
|
|
||||||
"wss://api.dev.kittycad.io/ws/modeling/commands?webrtc=false",
|
|
||||||
std::env::var("KITTYCAD_API_TOKEN").unwrap().as_str(),
|
|
||||||
"modeling-app-tests",
|
|
||||||
export_dir_str,
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
let _ = execute(program, &mut mem, BodyType::Root, &mut engine)?;
|
|
||||||
// Send an export request to the engine.
|
|
||||||
engine.send_modeling_cmd(
|
|
||||||
uuid::Uuid::new_v4(),
|
|
||||||
SourceRange::default(),
|
|
||||||
kittycad::types::ModelingCmd::Export {
|
|
||||||
entity_ids: vec![],
|
|
||||||
format: kittycad::types::OutputFormat::Gltf {
|
|
||||||
presentation: kittycad::types::Presentation::Pretty,
|
|
||||||
storage: kittycad::types::Storage::Embedded,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
)?;
|
|
||||||
|
|
||||||
engine.wait_for_files().await;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
#[tokio::test(flavor = "multi_thread")]
|
|
||||||
async fn test_export_file() {
|
|
||||||
let ast = r#"const part001 = startSketchAt([-0.01, -0.06])
|
|
||||||
|> line([0, 20], %)
|
|
||||||
|> line([5, 0], %)
|
|
||||||
|> line([-10, 5], %)
|
|
||||||
|> close(%)
|
|
||||||
|> extrude(4, %)
|
|
||||||
|
|
||||||
show(part001)"#;
|
|
||||||
parse_execute_export(ast).await.unwrap();
|
|
||||||
|
|
||||||
// Ensure we have a file called "part001.gltf" in the export directory.
|
|
||||||
let export_dir = std::path::Path::new("/tmp/");
|
|
||||||
let export_file = export_dir.join("part001.gltf");
|
|
||||||
assert!(export_file.exists());
|
|
||||||
// Make sure the file is not empty.
|
|
||||||
assert!(export_file.metadata().unwrap().len() != 0);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Reference in New Issue
Block a user