Add ocs_doc_api: object-oriented CAD entity API (v2)

New crate crates/ocs_doc_api: object-centric facade (DocApi -> Document ->
collections -> typed handles), transport-agnostic wire layer (DocApiEnvelope =
single op | read-only query batch), per-op autocommit (no write transactions),
bulk ops with upfront-validation all-or-nothing, structured ApiError, and
build-time codegen (spec/entities.toml -> ops/query enums, api_reference.md,
binding_schema.json).

ocs_plugin_api: append-only PluginRequest::DocApiRequest / PluginResponse::
DocApiResponse (serde_bytes payload) + defaulted HostApi::doc_api_dispatch.

Host: DocApiBackend impl for HostSession (src/app/doc_api.rs) mapping to scene
primitives (solid_models lift-on-miss, register_prepared_solid_model, meshes
metrics), entity conversions (doc_api_convert.rs), HostSession accessors +
doc_api_dispatch override.

Tests: 592 host lib (incl. 7 DocApi integration tests: create/boolean/query,
unknown-id, transform-many all-or-nothing, query-batch cap, 2D/geometric/DWG
roundtrips), 8 crate unit tests. Examples + README/ARCHITECTURE/IMPLEMENTATION docs.
This commit is contained in:
Sebastian committed 2026-09-06 00:15:27 +02:00
1 parent 9129c85f97
commit e41086b058
44 files changed
+4837 -12

No files matched your search

+40
View File
@@ -0,0 +1,40 @@
//! Stable entity identity (plan §2 decision #7).
use serde::{Deserialize, Serialize};
/// A stable u64 handle to a first-level document entity, decoupled from any
/// internal engine/kernel pointer. Value-compatible with `acadrust::Handle` —
/// kernel keys never cross the API boundary.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, PartialOrd, Ord, Serialize, Deserialize)]
#[serde(transparent)]
pub struct ObjectId(pub u64);
impl ObjectId {
/// The null / absent handle (`acadrust::Handle::NULL` value `0`).
pub const NULL: ObjectId = ObjectId(0);
pub const fn as_u64(self) -> u64 {
self.0
}
pub const fn is_null(self) -> bool {
self.0 == 0
}
/// Build from a raw u64 (e.g. an `acadrust::Handle`'s value).
pub const fn from_u64(v: u64) -> Self {
Self(v)
}
/// Build from an `acadrust::Handle` (host/ipc feature).
#[cfg(any(feature = "host", feature = "ipc", test))]
pub fn from_handle(h: acadrust::Handle) -> Self {
Self(h.value())
}
/// Convert to an `acadrust::Handle` (host/ipc feature).
#[cfg(any(feature = "host", feature = "ipc", test))]
pub fn to_handle(self) -> acadrust::Handle {
acadrust::Handle::new(self.0)
}
}