forked from 1b-agent/opencadstudio-upstream
General improvements on API
This commit is contained in:
1 parent
56e09cd3f5
commit
55f61a4327
30 files changed
+1820
-2565
No files matched your search
@@ -1,4 +1,4 @@
|
||||
//! Spec↔wire consistency tests (enforces the codegen contract the headers
|
||||
//! Spec↔wire consistency tests (enforces the codegen contract the headers
|
||||
//! promise): every `op`/`query` name in `spec/entities.toml` maps to an existing
|
||||
//! `Operation`/`Query` variant, and the wire enums are append-only relative to a
|
||||
//! recorded baseline (bincode discriminant stability).
|
||||
@@ -37,151 +37,50 @@ fn spec() -> Spec {
|
||||
|
||||
/// The variant names of the `Operation` enum, in declaration order.
|
||||
fn operation_variants() -> Vec<String> {
|
||||
use ocs_doc_api::ops::{
|
||||
BoolOp, Curve2Spec, InsertSpec, Operation, PlacementSpec, SolidPrimitive, ViewportSpec,
|
||||
};
|
||||
use ocs_doc_api::ops::{BoolOp, Curve2Spec, InsertSpec, Operation, PlacementSpec, SolidPrimitive, ViewportSpec};
|
||||
use ocs_doc_api::ObjectId;
|
||||
let _marker: Vec<Operation> = vec![
|
||||
Operation::CreateSolid(SolidPrimitive::Sphere {
|
||||
centre: [0.0; 3],
|
||||
radius: 1.0,
|
||||
}),
|
||||
Operation::CreateSolid(SolidPrimitive::Sphere { centre: [0.0; 3], radius: 1.0 }),
|
||||
Operation::CreateCurve(Curve2Spec::Point { position: [0.0; 3] }),
|
||||
Operation::Extrude {
|
||||
profile: ObjectId::from_u64(0),
|
||||
direction: [0.0; 3],
|
||||
},
|
||||
Operation::Revolve {
|
||||
profile: ObjectId::from_u64(0),
|
||||
axis: ([0.0; 3], [0.0; 3]),
|
||||
angle: 0.0,
|
||||
},
|
||||
Operation::Transform {
|
||||
id: ObjectId::from_u64(0),
|
||||
placement: PlacementSpec::IDENTITY,
|
||||
},
|
||||
Operation::SolidBoolean {
|
||||
op: BoolOp::Union,
|
||||
a: ObjectId::from_u64(0),
|
||||
b: ObjectId::from_u64(0),
|
||||
erase_sources: true,
|
||||
},
|
||||
Operation::AddVertex {
|
||||
id: ObjectId::from_u64(0),
|
||||
at: 0,
|
||||
point: [0.0; 3],
|
||||
},
|
||||
Operation::Delete {
|
||||
id: ObjectId::from_u64(0),
|
||||
},
|
||||
Operation::Extrude { profile: ObjectId::from_u64(0), direction: [0.0; 3] },
|
||||
Operation::Revolve { profile: ObjectId::from_u64(0), axis: ([0.0; 3], [0.0; 3]), angle: 0.0 },
|
||||
Operation::Transform { id: ObjectId::from_u64(0), placement: PlacementSpec::IDENTITY },
|
||||
Operation::SolidBoolean { op: BoolOp::Union, a: ObjectId::from_u64(0), b: ObjectId::from_u64(0), erase_sources: true },
|
||||
Operation::AddVertex { id: ObjectId::from_u64(0), at: 0, point: [0.0; 3] },
|
||||
Operation::Delete { id: ObjectId::from_u64(0) },
|
||||
Operation::CreateMany(vec![]),
|
||||
Operation::TransformMany {
|
||||
ids: vec![],
|
||||
placement: PlacementSpec::IDENTITY,
|
||||
},
|
||||
Operation::TransformMany { ids: vec![], placement: PlacementSpec::IDENTITY },
|
||||
Operation::DeleteMany(vec![]),
|
||||
Operation::CreateInsert(InsertSpec {
|
||||
block_name: String::new(),
|
||||
insert_point: [0.0; 3],
|
||||
scale: 1.0,
|
||||
rotation: 0.0,
|
||||
}),
|
||||
Operation::CreateViewport(ViewportSpec {
|
||||
center: [0.0; 3],
|
||||
width: 0.0,
|
||||
height: 0.0,
|
||||
view_target: [0.0; 3],
|
||||
view_height: 0.0,
|
||||
}),
|
||||
Operation::CreateText(ocs_doc_api::ops::TextSpec {
|
||||
value: String::new(),
|
||||
insertion_point: [0.0; 3],
|
||||
height: 0.0,
|
||||
rotation: 0.0,
|
||||
}),
|
||||
Operation::CreateMText(ocs_doc_api::ops::MTextSpec {
|
||||
value: String::new(),
|
||||
insertion_point: [0.0; 3],
|
||||
height: 0.0,
|
||||
}),
|
||||
Operation::SetTextContent {
|
||||
id: ObjectId::from_u64(0),
|
||||
value: String::new(),
|
||||
},
|
||||
Operation::CreateHatch(ocs_doc_api::ops::HatchSpec {
|
||||
boundary: vec![],
|
||||
solid: true,
|
||||
}),
|
||||
Operation::CreateDimensionLinear(ocs_doc_api::ops::DimensionSpec {
|
||||
first_point: [0.0; 3],
|
||||
second_point: [0.0; 3],
|
||||
definition_point: [0.0; 3],
|
||||
}),
|
||||
Operation::SetAttribute {
|
||||
id: ObjectId::from_u64(0),
|
||||
tag: String::new(),
|
||||
value: String::new(),
|
||||
},
|
||||
Operation::SetViewportView {
|
||||
id: ObjectId::from_u64(0),
|
||||
view_target: [0.0; 3],
|
||||
view_height: 0.0,
|
||||
},
|
||||
Operation::CreateInsert(InsertSpec { block_name: String::new(), insert_point: [0.0; 3], scale: 1.0, rotation: 0.0 }),
|
||||
Operation::CreateViewport(ViewportSpec { center: [0.0; 3], width: 0.0, height: 0.0, view_target: [0.0; 3], view_height: 0.0 }),
|
||||
Operation::CreateText(ocs_doc_api::ops::TextSpec { value: String::new(), insertion_point: [0.0; 3], height: 0.0, rotation: 0.0 }),
|
||||
Operation::CreateMText(ocs_doc_api::ops::MTextSpec { value: String::new(), insertion_point: [0.0; 3], height: 0.0 }),
|
||||
Operation::SetTextContent { id: ObjectId::from_u64(0), value: String::new() },
|
||||
Operation::CreateHatch(ocs_doc_api::ops::HatchSpec { boundary: vec![], solid: true }),
|
||||
Operation::CreateDimensionLinear(ocs_doc_api::ops::DimensionSpec { first_point: [0.0; 3], second_point: [0.0; 3], definition_point: [0.0; 3] }),
|
||||
Operation::SetAttribute { id: ObjectId::from_u64(0), tag: String::new(), value: String::new() },
|
||||
Operation::SetViewportView { id: ObjectId::from_u64(0), view_target: [0.0; 3], view_height: 0.0 },
|
||||
Operation::CreateRasterImage(ocs_doc_api::ops::RasterImageSpec {
|
||||
file_path: String::new(),
|
||||
insertion_point: [0.0; 3],
|
||||
u_vector: [0.0; 3],
|
||||
v_vector: [0.0; 3],
|
||||
size: [0.0; 2],
|
||||
file_path: String::new(), insertion_point: [0.0; 3], u_vector: [0.0; 3], v_vector: [0.0; 3], size: [0.0; 2],
|
||||
}),
|
||||
Operation::Loft { profiles: vec![] },
|
||||
Operation::CreateDimensionRadius(ocs_doc_api::ops::DimensionRadialSpec {
|
||||
center: [0.0; 3],
|
||||
point: [0.0; 3],
|
||||
}),
|
||||
Operation::CreateDimensionDiameter(ocs_doc_api::ops::DimensionRadialSpec {
|
||||
center: [0.0; 3],
|
||||
point: [0.0; 3],
|
||||
}),
|
||||
Operation::CreateDimensionAngular(ocs_doc_api::ops::DimensionAngularSpec {
|
||||
vertex: [0.0; 3],
|
||||
first_point: [0.0; 3],
|
||||
second_point: [0.0; 3],
|
||||
arc_location: [0.0; 3],
|
||||
}),
|
||||
Operation::CreateDimensionRadius(ocs_doc_api::ops::DimensionRadialSpec { center: [0.0; 3], point: [0.0; 3] }),
|
||||
Operation::CreateDimensionDiameter(ocs_doc_api::ops::DimensionRadialSpec { center: [0.0; 3], point: [0.0; 3] }),
|
||||
Operation::CreateDimensionAngular(ocs_doc_api::ops::DimensionAngularSpec { vertex: [0.0; 3], first_point: [0.0; 3], second_point: [0.0; 3], arc_location: [0.0; 3] }),
|
||||
Operation::CreateAttributeDefinition(ocs_doc_api::ops::AttributeDefinitionSpec {
|
||||
tag: String::new(),
|
||||
prompt: String::new(),
|
||||
default_value: String::new(),
|
||||
insertion_point: [0.0; 3],
|
||||
height: 0.0,
|
||||
rotation: 0.0,
|
||||
}),
|
||||
Operation::CreateTable(ocs_doc_api::ops::TableSpec {
|
||||
insertion_point: [0.0; 3],
|
||||
data: vec![],
|
||||
}),
|
||||
Operation::CreateDimensionAngular2Ln(ocs_doc_api::ops::DimensionAngularSpec {
|
||||
vertex: [0.0; 3],
|
||||
first_point: [0.0; 3],
|
||||
second_point: [0.0; 3],
|
||||
arc_location: [0.0; 3],
|
||||
tag: String::new(), prompt: String::new(), default_value: String::new(), insertion_point: [0.0; 3], height: 0.0, rotation: 0.0,
|
||||
}),
|
||||
Operation::CreateTable(ocs_doc_api::ops::TableSpec { insertion_point: [0.0; 3], data: vec![] }),
|
||||
Operation::CreateDimensionAngular2Ln(ocs_doc_api::ops::DimensionAngularSpec { vertex: [0.0; 3], first_point: [0.0; 3], second_point: [0.0; 3], arc_location: [0.0; 3] }),
|
||||
];
|
||||
// Derive the variant names by serializing a probe of each and reading the
|
||||
// bincode variant index -> name map is not available; instead match by
|
||||
// constructing each and using a tiny name extractor via Debug prefix.
|
||||
_marker
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, op)| {
|
||||
let wire = bincode::serialize(op).unwrap();
|
||||
assert_eq!(
|
||||
u32::from_le_bytes(wire[..4].try_into().unwrap()) as usize,
|
||||
index
|
||||
);
|
||||
.map(|op| {
|
||||
let dbg = format!("{:?}", op);
|
||||
dbg.split(|c: char| c == '(' || c == ' ' || c == '{')
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.to_string()
|
||||
dbg.split(|c: char| c == '(' || c == ' ' || c == '{').next().unwrap_or("").to_string()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@@ -191,56 +90,24 @@ fn query_variants() -> Vec<String> {
|
||||
use ocs_doc_api::query::Query;
|
||||
use ocs_doc_api::ObjectId;
|
||||
let marker: Vec<Query> = vec![
|
||||
Query::GetEntity {
|
||||
id: ObjectId::from_u64(0),
|
||||
},
|
||||
Query::GetBounds {
|
||||
id: ObjectId::from_u64(0),
|
||||
},
|
||||
Query::GetCentroid {
|
||||
id: ObjectId::from_u64(0),
|
||||
},
|
||||
Query::GetVolume {
|
||||
id: ObjectId::from_u64(0),
|
||||
},
|
||||
Query::GetIntersects {
|
||||
a: ObjectId::from_u64(0),
|
||||
b: ObjectId::from_u64(0),
|
||||
},
|
||||
Query::GetEntity { id: ObjectId::from_u64(0) },
|
||||
Query::GetBounds { id: ObjectId::from_u64(0) },
|
||||
Query::GetCentroid { id: ObjectId::from_u64(0) },
|
||||
Query::GetVolume { id: ObjectId::from_u64(0) },
|
||||
Query::GetIntersects { a: ObjectId::from_u64(0), b: ObjectId::from_u64(0) },
|
||||
Query::GetGeometryRevision,
|
||||
Query::GetTextContent {
|
||||
id: ObjectId::from_u64(0),
|
||||
},
|
||||
Query::GetHatchBoundary {
|
||||
id: ObjectId::from_u64(0),
|
||||
},
|
||||
Query::GetDimensionMeasurement {
|
||||
id: ObjectId::from_u64(0),
|
||||
},
|
||||
Query::GetAttributes {
|
||||
id: ObjectId::from_u64(0),
|
||||
},
|
||||
Query::GetBlockEntities {
|
||||
block_name: String::new(),
|
||||
},
|
||||
Query::GetViewportView {
|
||||
id: ObjectId::from_u64(0),
|
||||
},
|
||||
Query::GetTextContent { id: ObjectId::from_u64(0) },
|
||||
Query::GetHatchBoundary { id: ObjectId::from_u64(0) },
|
||||
Query::GetDimensionMeasurement { id: ObjectId::from_u64(0) },
|
||||
Query::GetAttributes { id: ObjectId::from_u64(0) },
|
||||
Query::GetBlockEntities { block_name: String::new() },
|
||||
Query::GetViewportView { id: ObjectId::from_u64(0) },
|
||||
];
|
||||
marker
|
||||
.iter()
|
||||
.enumerate()
|
||||
.map(|(index, q)| {
|
||||
let wire = bincode::serialize(q).unwrap();
|
||||
assert_eq!(
|
||||
u32::from_le_bytes(wire[..4].try_into().unwrap()) as usize,
|
||||
index
|
||||
);
|
||||
.map(|q| {
|
||||
let dbg = format!("{:?}", q);
|
||||
dbg.split(|c: char| c == '(' || c == ' ' || c == '{')
|
||||
.next()
|
||||
.unwrap_or("")
|
||||
.to_string()
|
||||
dbg.split(|c: char| c == '(' || c == ' ' || c == '{').next().unwrap_or("").to_string()
|
||||
})
|
||||
.collect()
|
||||
}
|
||||
@@ -256,26 +123,17 @@ fn every_spec_op_and_query_maps_to_an_enum_variant() {
|
||||
for m in fam.constructor.iter().chain(fam.method.iter()) {
|
||||
if let Some(op) = &m.op {
|
||||
if !op_names.contains(op) {
|
||||
missing.push(format!(
|
||||
"Operation::{op} (family {})",
|
||||
fam.handle.as_deref().unwrap_or("?")
|
||||
));
|
||||
missing.push(format!("Operation::{op} (family {})", fam.handle.as_deref().unwrap_or("?")));
|
||||
}
|
||||
}
|
||||
if let Some(q) = &m.query {
|
||||
if !query_names.contains(q) {
|
||||
missing.push(format!(
|
||||
"Query::{q} (family {})",
|
||||
fam.handle.as_deref().unwrap_or("?")
|
||||
));
|
||||
missing.push(format!("Query::{q} (family {})", fam.handle.as_deref().unwrap_or("?")));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
assert!(
|
||||
missing.is_empty(),
|
||||
"spec references ops/queries with no enum variant: {missing:?}"
|
||||
);
|
||||
assert!(missing.is_empty(), "spec references ops/queries with no enum variant: {missing:?}");
|
||||
}
|
||||
|
||||
/// Recorded baseline of the `Operation` variant order (append-only contract).
|
||||
|
||||
Reference in new issue
Block a user