1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
// SPDX-License-Identifier: Apache-2.0
//! Parametric construction history.
use schemars::JsonSchema;
use serde::{Deserialize, Serialize};
use std::collections::BTreeMap;
/// A named parametric-model variant (e.g. CAD "configuration") with its own
/// material and property overrides.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Configuration {
/// Globally unique deterministic identifier for this native record.
pub id: String,
/// Source configuration name.
pub name: String,
/// Material assigned in this configuration, when overridden; `None` when the
/// configuration inherits the part's default material.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub material: Option<String>,
/// Source custom-property name/value pairs local to this configuration.
#[serde(default)]
pub properties: BTreeMap<String, String>,
}
/// One parametric construction-history feature (e.g. an extrude or fillet operation).
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct Feature {
/// Globally unique deterministic identifier for this native record.
pub id: String,
/// Native identifier of this feature, when the source assigned one.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub source_id: Option<String>,
/// Native identifier of this feature's parent in the construction tree, when
/// the source recorded parent/child feature dependency.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub parent_source_id: Option<String>,
/// Position of this feature in the construction-history timeline, in
/// regeneration order.
pub ordinal: u32,
/// Feature display name.
pub name: String,
/// Native feature-type tag (e.g. `"Extrude"`, `"Fillet"`).
pub kind: String,
/// Whether this feature is suppressed and excluded from regeneration.
#[serde(default)]
pub suppressed: bool,
/// Source parametric input values keyed by parameter name.
#[serde(default)]
pub parameters: BTreeMap<String, String>,
/// Source custom-property name/value pairs local to this feature.
#[serde(default)]
pub properties: BTreeMap<String, String>,
}
/// The full parametric construction-history timeline for a part.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct FeatureHistory {
/// Globally unique deterministic identifier for this native record.
pub id: String,
/// Source part display name, when recorded.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub part_name: Option<String>,
/// Named parametric-model variants defined on this part.
#[serde(default)]
pub configurations: Vec<Configuration>,
/// Ordered construction-history features, in regeneration order.
#[serde(default)]
pub features: Vec<Feature>,
}
/// Native feature-input stream retained for parametric replay and rewrite.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct FeatureInputLane {
/// Stable source-derived identifier for this feature-input record.
pub id: String,
/// Configuration this input lane applies to, when the source scoped inputs
/// per configuration; `None` when the lane applies to all configurations.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub configuration: Option<String>,
/// Complete native feature-input byte stream, retained undecoded for
/// parametric replay and native rewrite.
#[serde(with = "crate::bytes")]
#[schemars(with = "String")]
pub native_payload: Vec<u8>,
/// Typed sketch-entity markers located within `native_payload`.
#[serde(default)]
pub sketch_entities: Vec<SketchInputEntity>,
}
/// One typed sketch-entity marker inside a native feature-input stream.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct SketchInputEntity {
/// Globally unique deterministic identifier for this native record.
pub id: String,
/// Position of this marker within the owning `FeatureInputLane`, in stream order.
pub ordinal: u32,
/// Byte offset of this marker within `FeatureInputLane::native_payload`.
pub offset: u64,
/// Sketch-entity kind this marker identifies.
pub kind: SketchInputKind,
}
/// Kind of sketch entity referenced by a native feature-input marker.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum SketchInputKind {
/// A sketch point.
Point,
/// A general sketch curve.
Curve,
/// A sketch arc.
Arc,
/// A sketch point bound by a geometric constraint.
ConstrainedPoint,
/// A native code not in the known vocabulary, preserved verbatim.
Native(u32),
}
impl SketchInputKind {
/// Maps a native sketch-entity type code to its typed kind, falling back to
/// [`SketchInputKind::Native`] for unrecognized codes.
pub fn from_native_code(code: u32) -> Self {
match code {
0 => Self::Point,
1 => Self::Curve,
2 => Self::Arc,
3 => Self::ConstrainedPoint,
value => Self::Native(value),
}
}
/// Returns the native sketch-entity type code for this kind, the inverse of
/// [`SketchInputKind::from_native_code`].
pub fn native_code(self) -> u32 {
match self {
Self::Point => 0,
Self::Curve => 1,
Self::Arc => 2,
Self::ConstrainedPoint => 3,
Self::Native(value) => value,
}
}
}
/// ASM construction-history container and its linked delta states.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AsmHistory {
/// Globally unique deterministic identifier for this native record.
pub id: String,
/// Byte offset of the `history_stream` identifier, or zero when no preamble exists.
pub byte_offset: u64,
/// Declared byte length of the ASM history stream from its preamble, when present.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub stream_size: Option<i64>,
/// Highest state id watermark recorded in the history preamble, when present.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub high_water_mark: Option<i64>,
/// Linked `delta_state` nodes forming the construction-state chain.
pub states: Vec<AsmDeltaState>,
}
/// One byte-framed ASM `delta_state` node.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AsmDeltaState {
/// Globally unique deterministic identifier for this native record.
pub id: String,
/// Byte offset of the leading `END` token immediately before this `delta_state` record.
pub byte_offset: u64,
/// Construction-state id; the head node's `state_id` equals the history
/// stream preamble's first field.
pub state_id: i64,
/// Source version tag on the `delta_state` record; observed constant `1`.
pub version_flag: i64,
/// Source state tag on the `delta_state` record; observed constant `0`.
pub state_flag: i64,
/// Reference to the previous state in the doubly-linked chain; `None` on the head node.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub previous_ref: Option<i64>,
/// Reference to the next state in the doubly-linked chain; `None` on the tail node.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub next_ref: Option<i64>,
/// Sequential position of this node in the chain (0, 1, 2, ...).
pub node_index: i64,
/// Reference to a partner state, when the source recorded one.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub partner_ref: Option<i64>,
/// Reference to the owning entity or container of this state.
pub owner_ref: i64,
/// Per-entity insert/delete/update bulletins recorded in this state.
#[serde(default)]
pub bulletin_boards: Vec<AsmBulletinBoard>,
/// State-local SAB entity revisions referenced by the bulletins.
#[serde(default)]
pub records: Vec<AsmHistoryRecord>,
}
/// One state-local SAB record retained byte-for-byte for replay and native write.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AsmHistoryRecord {
/// Globally unique deterministic identifier for this native record.
pub id: String,
/// Index of this record within its owning `delta_state`'s local record table.
pub index: u64,
/// Source class/record-type name.
pub name: String,
/// Complete undecoded source record bytes, retained for native replay/write.
#[serde(with = "crate::bytes")]
#[schemars(with = "String")]
pub raw_bytes: Vec<u8>,
}
/// One `BulletinBoard` in an ASM construction state.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AsmBulletinBoard {
/// Globally unique deterministic identifier for this native record.
pub id: String,
/// Byte offset of this board's leading presence token.
pub byte_offset: u64,
/// Reference to the entity or container this bulletin board is attached to.
pub owner_ref: i64,
/// Sequential bulletin-board number within its owning state.
pub number: i64,
/// Per-entity insert/delete/update change bulletins carried by this board.
pub changes: Vec<AsmEntityChange>,
}
/// Entity revision pair carried by a `BulletinBoard`.
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, JsonSchema)]
pub struct AsmEntityChange {
/// Globally unique deterministic identifier for this native record.
pub id: String,
/// Byte offset of this change's leading presence token.
pub byte_offset: u64,
/// Whether this bulletin records an entity insert, delete, or update.
pub kind: AsmEntityChangeKind,
/// Reference to the entity revision before the change; `None` on insert.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub old_ref: Option<i64>,
/// Reference to the entity revision after the change; `None` on delete.
#[serde(default, skip_serializing_if = "Option::is_none")]
pub new_ref: Option<i64>,
}
/// The kind of change one ASM bulletin records against an entity revision.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, JsonSchema)]
#[serde(rename_all = "snake_case")]
pub enum AsmEntityChangeKind {
/// A new entity revision was created.
Insert,
/// An entity revision was removed.
Delete,
/// An entity revision was modified.
Update,
}