290 lines
9.6 KiB
Rust
290 lines
9.6 KiB
Rust
//! Wasm bindings for `kcl`.
|
|
|
|
use gloo_utils::format::JsValueSerdeExt;
|
|
use kcl_lib::{pretty::NumericSuffix, CoreDump, Point2d, Program};
|
|
use wasm_bindgen::prelude::*;
|
|
|
|
// wasm_bindgen wrapper for execute
|
|
#[wasm_bindgen]
|
|
pub async fn kcl_lint(program_ast_json: &str) -> Result<JsValue, JsValue> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let program: Program = serde_json::from_str(program_ast_json).map_err(|e| e.to_string())?;
|
|
let mut findings = vec![];
|
|
for discovered_finding in program.lint_all().into_iter().flatten() {
|
|
findings.push(discovered_finding);
|
|
}
|
|
|
|
Ok(JsValue::from_serde(&findings).map_err(|e| e.to_string())?)
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub fn parse_wasm(kcl_program_source: &str) -> Result<JsValue, String> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let (program, errs) = Program::parse(kcl_program_source).map_err(String::from)?;
|
|
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
|
// gloo-serialize crate instead.
|
|
JsValue::from_serde(&(program, errs)).map_err(|e| e.to_string())
|
|
}
|
|
|
|
// wasm_bindgen wrapper for recast
|
|
// test for this function and by extension the recaster are done in javascript land src/lang/recast.test.ts
|
|
#[wasm_bindgen]
|
|
pub fn recast_wasm(json_str: &str) -> Result<JsValue, JsError> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let program: Program = serde_json::from_str(json_str).map_err(JsError::from)?;
|
|
Ok(JsValue::from_serde(&program.recast())?)
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub fn format_number(value: f64, suffix_json: &str) -> Result<String, JsError> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let suffix: NumericSuffix = serde_json::from_str(suffix_json).map_err(JsError::from)?;
|
|
Ok(kcl_lib::pretty::format_number(value, suffix))
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub fn is_points_ccw(points: &[f64]) -> i32 {
|
|
console_error_panic_hook::set_once();
|
|
|
|
kcl_lib::std_utils::is_points_ccw_wasm(points)
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub struct TangentialArcInfoOutputWasm {
|
|
/// The geometric center of the arc x.
|
|
pub center_x: f64,
|
|
/// The geometric center of the arc y.
|
|
pub center_y: f64,
|
|
/// The midpoint of the arc x.
|
|
pub arc_mid_point_x: f64,
|
|
/// The midpoint of the arc y.
|
|
pub arc_mid_point_y: f64,
|
|
/// The radius of the arc.
|
|
pub radius: f64,
|
|
/// Start angle of the arc in radians.
|
|
pub start_angle: f64,
|
|
/// End angle of the arc in radians.
|
|
pub end_angle: f64,
|
|
/// Flag to determine if the arc is counter clockwise.
|
|
pub ccw: i32,
|
|
/// The length of the arc.
|
|
pub arc_length: f64,
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub fn get_tangential_arc_to_info(
|
|
arc_start_point_x: f64,
|
|
arc_start_point_y: f64,
|
|
arc_end_point_x: f64,
|
|
arc_end_point_y: f64,
|
|
tan_previous_point_x: f64,
|
|
tan_previous_point_y: f64,
|
|
obtuse: bool,
|
|
) -> TangentialArcInfoOutputWasm {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let result = kcl_lib::std_utils::get_tangential_arc_to_info(kcl_lib::std_utils::TangentialArcInfoInput {
|
|
arc_start_point: [arc_start_point_x, arc_start_point_y],
|
|
arc_end_point: [arc_end_point_x, arc_end_point_y],
|
|
tan_previous_point: [tan_previous_point_x, tan_previous_point_y],
|
|
obtuse,
|
|
});
|
|
TangentialArcInfoOutputWasm {
|
|
center_x: result.center[0],
|
|
center_y: result.center[1],
|
|
arc_mid_point_x: result.arc_mid_point[0],
|
|
arc_mid_point_y: result.arc_mid_point[1],
|
|
radius: result.radius,
|
|
start_angle: result.start_angle,
|
|
end_angle: result.end_angle,
|
|
ccw: result.ccw,
|
|
arc_length: result.arc_length,
|
|
}
|
|
}
|
|
|
|
/// Get a coredump.
|
|
#[wasm_bindgen]
|
|
pub async fn coredump(core_dump_manager: kcl_lib::wasm_engine::CoreDumpManager) -> Result<JsValue, String> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let core_dumper = kcl_lib::wasm_engine::CoreDumper::new(core_dump_manager);
|
|
let dump = core_dumper.dump().await.map_err(|e| e.to_string())?;
|
|
|
|
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
|
// gloo-serialize crate instead.
|
|
JsValue::from_serde(&dump).map_err(|e| e.to_string())
|
|
}
|
|
|
|
/// Get the default app settings.
|
|
#[wasm_bindgen]
|
|
pub fn default_app_settings() -> Result<JsValue, String> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let settings = kcl_lib::Configuration::default();
|
|
|
|
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
|
// gloo-serialize crate instead.
|
|
JsValue::from_serde(&settings).map_err(|e| e.to_string())
|
|
}
|
|
|
|
/// Parse the app settings.
|
|
#[wasm_bindgen]
|
|
pub fn parse_app_settings(toml_str: &str) -> Result<JsValue, String> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let settings = kcl_lib::Configuration::backwards_compatible_toml_parse(toml_str).map_err(|e| e.to_string())?;
|
|
|
|
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
|
// gloo-serialize crate instead.
|
|
JsValue::from_serde(&settings).map_err(|e| e.to_string())
|
|
}
|
|
|
|
/// Get the default project settings.
|
|
#[wasm_bindgen]
|
|
pub fn default_project_settings() -> Result<JsValue, String> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let settings = kcl_lib::ProjectConfiguration::default();
|
|
|
|
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
|
// gloo-serialize crate instead.
|
|
JsValue::from_serde(&settings).map_err(|e| e.to_string())
|
|
}
|
|
|
|
/// Parse (deserialize) the project settings.
|
|
#[wasm_bindgen]
|
|
pub fn parse_project_settings(toml_str: &str) -> Result<JsValue, String> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let settings =
|
|
kcl_lib::ProjectConfiguration::backwards_compatible_toml_parse(toml_str).map_err(|e| e.to_string())?;
|
|
|
|
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
|
// gloo-serialize crate instead.
|
|
JsValue::from_serde(&settings).map_err(|e| e.to_string())
|
|
}
|
|
|
|
/// Serialize the configuration settings.
|
|
#[wasm_bindgen]
|
|
pub fn serialize_configuration(val: JsValue) -> Result<JsValue, String> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let config: kcl_lib::Configuration = val.into_serde().map_err(|e| e.to_string())?;
|
|
|
|
let toml_str = toml::to_string_pretty(&config).map_err(|e| e.to_string())?;
|
|
|
|
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
|
// gloo-serialize crate instead.
|
|
Ok(JsValue::from_str(&toml_str))
|
|
}
|
|
|
|
/// Serialize the project configuration settings.
|
|
#[wasm_bindgen]
|
|
pub fn serialize_project_configuration(val: JsValue) -> Result<JsValue, String> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let config: kcl_lib::ProjectConfiguration = val.into_serde().map_err(|e| e.to_string())?;
|
|
|
|
let toml_str = toml::to_string_pretty(&config).map_err(|e| e.to_string())?;
|
|
|
|
// The serde-wasm-bindgen does not work here because of weird HashMap issues so we use the
|
|
// gloo-serialize crate instead.
|
|
Ok(JsValue::from_str(&toml_str))
|
|
}
|
|
|
|
static ALLOWED_DECODING_FORMATS: &[data_encoding::Encoding] = &[
|
|
data_encoding::BASE64,
|
|
data_encoding::BASE64URL,
|
|
data_encoding::BASE64URL_NOPAD,
|
|
data_encoding::BASE64_MIME,
|
|
data_encoding::BASE64_NOPAD,
|
|
];
|
|
|
|
/// Base64 decode a string.
|
|
#[wasm_bindgen]
|
|
pub fn base64_decode(input: &str) -> Result<Vec<u8>, JsValue> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
// Forgive alt base64 decoding formats
|
|
for config in ALLOWED_DECODING_FORMATS {
|
|
if let Ok(data) = config.decode(input.as_bytes()) {
|
|
return Ok(data);
|
|
}
|
|
}
|
|
|
|
Err(JsValue::from_str("Invalid base64 encoding"))
|
|
}
|
|
|
|
#[wasm_bindgen]
|
|
pub struct WasmCircleParams {
|
|
pub center_x: f64,
|
|
pub center_y: f64,
|
|
pub radius: f64,
|
|
}
|
|
|
|
/// Calculate a circle from 3 points.
|
|
#[wasm_bindgen]
|
|
pub fn calculate_circle_from_3_points(ax: f64, ay: f64, bx: f64, by: f64, cx: f64, cy: f64) -> WasmCircleParams {
|
|
let result = kcl_lib::std::utils::calculate_circle_from_3_points([
|
|
Point2d { x: ax, y: ay },
|
|
Point2d { x: bx, y: by },
|
|
Point2d { x: cx, y: cy },
|
|
]);
|
|
|
|
WasmCircleParams {
|
|
center_x: result.center.x,
|
|
center_y: result.center.y,
|
|
radius: result.radius,
|
|
}
|
|
}
|
|
|
|
/// Takes a parsed KCL program and returns the Meta settings. If it's not
|
|
/// found, null is returned.
|
|
#[wasm_bindgen]
|
|
pub fn kcl_settings(program_json: &str) -> Result<JsValue, String> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let program: Program = serde_json::from_str(program_json).map_err(|e| e.to_string())?;
|
|
let settings = program.meta_settings().map_err(|e| e.to_string())?;
|
|
|
|
JsValue::from_serde(&settings).map_err(|e| e.to_string())
|
|
}
|
|
|
|
/// Takes a kcl string and Meta settings and changes the meta settings in the kcl string.
|
|
#[wasm_bindgen]
|
|
pub fn change_kcl_settings(code: &str, settings_str: &str) -> Result<String, String> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let settings: kcl_lib::MetaSettings = serde_json::from_str(settings_str).map_err(|e| e.to_string())?;
|
|
let program = Program::parse_no_errs(code).map_err(|e| e.to_string())?;
|
|
|
|
let new_program = program.change_meta_settings(settings).map_err(|e| e.to_string())?;
|
|
|
|
let formatted = new_program.recast();
|
|
|
|
Ok(formatted)
|
|
}
|
|
|
|
/// Returns true if the given KCL is empty or only contains settings that would
|
|
/// be auto-generated.
|
|
#[wasm_bindgen]
|
|
pub fn is_kcl_empty_or_only_settings(code: &str) -> Result<JsValue, String> {
|
|
console_error_panic_hook::set_once();
|
|
|
|
let program = Program::parse_no_errs(code).map_err(|e| e.to_string())?;
|
|
|
|
JsValue::from_serde(&program.is_empty_or_only_settings()).map_err(|e| e.to_string())
|
|
}
|
|
|
|
/// Get the version of the kcl library.
|
|
#[wasm_bindgen]
|
|
pub fn get_kcl_version() -> String {
|
|
console_error_panic_hook::set_once();
|
|
|
|
kcl_lib::version().to_string()
|
|
}
|