1#![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 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 new_objects: Vec<ObjectId>,
50 pub invalidates_ids: bool,
51}
52
53impl SceneGraphDelta {
54 pub fn new(new_graph: SceneGraph, new_objects: Vec<ObjectId>, invalidates_ids: bool) -> Self {
55 SceneGraphDelta {
56 new_graph,
57 new_objects,
58 invalidates_ids,
59 }
60 }
61}
62
63#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
64#[ts(export)]
65pub struct SourceDelta {}
66
67#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Deserialize, Serialize, ts_rs::TS)]
68#[ts(export, rename = "ApiObjectId")]
69pub struct ObjectId(pub usize);
70
71#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Ord, PartialOrd, Deserialize, Serialize, ts_rs::TS)]
72#[ts(export, rename = "ApiVersion")]
73pub struct Version(pub usize);
74
75#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Deserialize, Serialize, ts_rs::TS)]
76#[ts(export, rename = "ApiProjectId")]
77pub struct ProjectId(pub usize);
78
79#[derive(Debug, Clone, Copy, Hash, Eq, PartialEq, Deserialize, Serialize, ts_rs::TS)]
80#[ts(export, rename = "ApiFileId")]
81pub struct FileId(pub usize);
82
83#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
84#[ts(export, rename = "ApiFile")]
85pub struct File {
86 pub id: FileId,
87 pub path: String,
88 pub text: String,
89}
90
91#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
92#[ts(export, rename = "ApiSettings")]
93pub struct Settings {}
94
95#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
96pub struct Object {
97 pub id: ObjectId,
98 pub kind: ObjectKind,
99 pub label: String,
100 pub comments: String,
101 pub artifact_id: usize,
102 pub source: SourceRef,
103}
104
105#[allow(clippy::large_enum_variant)]
106#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
107pub enum ObjectKind {
108 Sketch(crate::sketch::Sketch),
109 Segment(crate::sketch::Segment),
110 Constraint(crate::sketch::Constraint),
111 Region,
113 Sweep,
114}
115
116#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
117pub enum Plane {
118 Object(ObjectId),
119 Default,
120}
121
122#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
123pub enum SourceRef {
124 Simple(SourceRange),
125 BackTrace(Vec<SourceRange>),
126}
127
128#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
129#[ts(export)]
130pub struct Number {
131 value: f64,
132 units: NumericSuffix,
133}
134
135#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
136#[ts(export)]
137pub enum Expr {
138 Number(Number),
139 Var(Number),
140 Variable(String),
141}
142
143#[derive(Clone, Copy, Debug, Eq, PartialEq, Serialize, Deserialize, ts_rs::TS)]
145#[repr(u32)]
146#[ts(export)]
147pub enum NumericSuffix {
148 None,
149 Count,
150 Length,
151 Angle,
152 Mm,
153 Cm,
154 M,
155 Inch,
156 Ft,
157 Yd,
158 Deg,
159 Rad,
160 Unknown,
161}
162
163#[derive(Debug, Clone, Deserialize, Serialize, ts_rs::TS)]
164#[ts(export)]
165pub struct Error {
166 pub msg: String,
167}
168
169impl Error {
170 pub fn file_id_in_use(id: FileId, path: &str) -> Self {
171 Error {
172 msg: format!("File ID already in use: {id:?}, currently used for `{path}`"),
173 }
174 }
175
176 pub fn bad_project(found: ProjectId, expected: Option<ProjectId>) -> Self {
177 let msg = match expected {
178 Some(expected) => format!("Project ID mismatch found: {found:?}, expected: {expected:?}"),
179 None => format!("No open project, found: {found:?}"),
180 };
181 Error { msg }
182 }
183
184 pub fn bad_version(found: Version, expected: Version) -> Self {
185 Error {
186 msg: format!("Version mismatch found: {found:?}, expected: {expected:?}"),
187 }
188 }
189
190 pub fn bad_file(found: FileId, expected: Option<FileId>) -> Self {
191 let msg = match expected {
192 Some(expected) => format!("File ID mismatch found: {found:?}, expected: {expected:?}"),
193 None => format!("File ID not found: {found:?}"),
194 };
195 Error { msg }
196 }
197
198 pub fn serialize(e: impl serde::ser::Error) -> Self {
199 Error {
200 msg: format!(
201 "Could not serialize successful KCL result. This is a bug in KCL and not in your code, please report this to Zoo. Details: {e}"
202 ),
203 }
204 }
205
206 pub fn deserialize(name: &str, e: impl serde::de::Error) -> Self {
207 Error {
208 msg: format!(
209 "Could not deserialize argument `{name}`. This is a bug in KCL and not in your code, please report this to Zoo. Details: {e}"
210 ),
211 }
212 }
213}
214
215pub type Result<T> = std::result::Result<T, Error>;