kcl_api/
lib.rs

1//! An API for controlling the KCL interpreter from the frontend.
2
3#![allow(async_fn_in_trait)]
4
5use kcl_error::SourceRange;
6use serde::{Deserialize, Serialize};
7
8pub mod sketch;
9
10pub trait LifecycleApi {
11    async fn open_project(&self, project: ProjectId, files: Vec<File>, open_file: FileId) -> Result<()>;
12    async fn add_file(&self, project: ProjectId, file: File) -> Result<()>;
13    async fn remove_file(&self, project: ProjectId, file: FileId) -> Result<()>;
14    // File changed on disk, etc. outside of the editor or applying undo, restore, etc.
15    async fn update_file(&self, project: ProjectId, file: FileId, text: String) -> Result<()>;
16    async fn switch_file(&self, project: ProjectId, file: FileId) -> Result<()>;
17    async fn refresh(&self, project: ProjectId) -> Result<()>;
18}
19
20#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
21#[ts(export)]
22pub struct SceneGraph {
23    pub project: ProjectId,
24    pub file: FileId,
25    pub version: Version,
26
27    pub objects: Vec<Object>,
28    pub settings: Settings,
29    pub sketch_mode: Option<ObjectId>,
30}
31
32impl SceneGraph {
33    pub fn empty(project: ProjectId, file: FileId, version: Version) -> Self {
34        SceneGraph {
35            project,
36            file,
37            version,
38            objects: Vec::new(),
39            settings: Settings {},
40            sketch_mode: None,
41        }
42    }
43}
44
45#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
46#[ts(export)]
47pub struct SceneGraphDelta {
48    pub new_graph: SceneGraph,
49    pub invalidates_ids: bool,
50}
51
52impl SceneGraphDelta {
53    pub fn new(new_graph: SceneGraph, invalidates_ids: bool) -> Self {
54        SceneGraphDelta {
55            new_graph,
56            invalidates_ids,
57        }
58    }
59}
60
61#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
62#[ts(export)]
63pub struct SourceDelta {}
64
65#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Deserialize, Serialize, ts_rs::TS)]
66#[ts(export, rename = "ApiObjectId")]
67pub struct ObjectId(pub usize);
68
69#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize, ts_rs::TS)]
70#[ts(export, rename = "ApiVersion")]
71pub struct Version(pub usize);
72
73#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Deserialize, Serialize, ts_rs::TS)]
74#[ts(export, rename = "ApiProjectId")]
75pub struct ProjectId(pub usize);
76
77#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Deserialize, Serialize, ts_rs::TS)]
78#[ts(export, rename = "ApiFileId")]
79pub struct FileId(pub usize);
80
81#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
82#[ts(export, rename = "ApiFile")]
83pub struct File {
84    pub id: FileId,
85    pub path: String,
86    pub text: String,
87}
88
89#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
90#[ts(export, rename = "ApiSettings")]
91pub struct Settings {}
92
93#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
94pub struct Object {
95    pub kind: ObjectKind,
96    pub artifact_id: usize,
97    pub source: SourceRef,
98}
99
100#[allow(clippy::large_enum_variant)]
101#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
102pub enum ObjectKind {
103    Sketch(crate::sketch::Sketch),
104    Segment(crate::sketch::Segment),
105    Constraint,
106    Sweep,
107}
108
109#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
110pub enum Plane {
111    Object(ObjectId),
112    Default,
113}
114
115#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
116pub enum SourceRef {
117    Simple(SourceRange),
118    BackTrace(Vec<SourceRange>),
119}
120
121pub trait Kind: std::fmt::Debug + Clone + ts_rs::TS {}
122
123#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
124#[ts(export)]
125pub struct Number {
126    value: f64,
127    units: NumericSuffix,
128}
129
130impl Kind for Number {}
131
132#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
133#[ts(export)]
134pub enum Expr {
135    Number(Number),
136    Var(Number),
137    Variable(String),
138}
139
140impl Kind for Expr {}
141
142// TODO share with kcl-lib
143#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, ts_rs::TS)]
144#[repr(u32)]
145#[ts(export)]
146pub enum NumericSuffix {
147    None,
148    Count,
149    Length,
150    Angle,
151    Mm,
152    Cm,
153    M,
154    Inch,
155    Ft,
156    Yd,
157    Deg,
158    Rad,
159    Unknown,
160}
161
162#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
163#[ts(export)]
164pub struct Error {
165    pub msg: String,
166}
167
168impl Error {
169    pub fn file_id_in_use(id: FileId, path: &str) -> Self {
170        Error {
171            msg: format!("File ID already in use: {id:?}, currently used for `{path}`"),
172        }
173    }
174
175    pub fn bad_project(found: ProjectId, expected: Option<ProjectId>) -> Self {
176        let msg = match expected {
177            Some(expected) => format!("Project ID mismatch found: {found:?}, expected: {expected:?}"),
178            None => format!("No open project, found: {found:?}"),
179        };
180        Error { msg }
181    }
182
183    pub fn bad_version(found: Version, expected: Version) -> Self {
184        Error {
185            msg: format!("Version mismatch found: {found:?}, expected: {expected:?}"),
186        }
187    }
188
189    pub fn bad_file(found: FileId, expected: Option<FileId>) -> Self {
190        let msg = match expected {
191            Some(expected) => format!("File ID mismatch found: {found:?}, expected: {expected:?}"),
192            None => format!("File ID not found: {found:?}"),
193        };
194        Error { msg }
195    }
196
197    pub fn serialize(e: impl serde::ser::Error) -> Self {
198        Error {
199            msg: format!(
200                "Could not serialize successful KCL result. This is a bug in KCL and not in your code, please report this to Zoo. Details: {e}"
201            ),
202        }
203    }
204
205    pub fn deserialize(name: &str, e: impl serde::de::Error) -> Self {
206        Error {
207            msg: format!(
208                "Could not deserialize argument `{name}`. This is a bug in KCL and not in your code, please report this to Zoo. Details: {e}"
209            ),
210        }
211    }
212}
213
214pub type Result<T> = std::result::Result<T, Error>;