forked from 1b-agent/opencadstudio-upstream
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:
1 parent
9129c85f97
commit
e41086b058
44 files changed
+4837
-12
No files matched your search
@@ -0,0 +1,77 @@
|
||||
//! The wire envelope (plan §7). One request = ONE write op OR a query batch
|
||||
//! (read-only batching is safe: no mutation, no undo, no rollback).
|
||||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::gen::{Operation, Query};
|
||||
use crate::id::ObjectId;
|
||||
use crate::query::QueryResult;
|
||||
use crate::revision::GeometryRevision;
|
||||
use crate::ENVELOPE_VERSION;
|
||||
|
||||
/// The single request unit crossing the transport.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct DocApiEnvelope {
|
||||
/// Crate protocol version (`ENVELOPE_VERSION`). Bridges must check this.
|
||||
pub version: u16,
|
||||
pub body: EnvelopeBody,
|
||||
}
|
||||
|
||||
impl DocApiEnvelope {
|
||||
pub fn op(operation: Operation) -> Self {
|
||||
Self { version: ENVELOPE_VERSION, body: EnvelopeBody::Op(operation) }
|
||||
}
|
||||
pub fn queries(queries: Vec<Query>) -> Self {
|
||||
Self { version: ENVELOPE_VERSION, body: EnvelopeBody::Queries(queries) }
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum EnvelopeBody {
|
||||
/// Exactly ONE write op (write batching removed, plan §13). Atomic by itself.
|
||||
Op(Operation),
|
||||
/// One-or-more read-only queries answered together (safe: no mutation/undo).
|
||||
Queries(Vec<Query>),
|
||||
}
|
||||
|
||||
/// The outcome of an applied write op.
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub enum OpOutcome {
|
||||
/// A new entity was created; carries its fresh `ObjectId`.
|
||||
NewId(ObjectId),
|
||||
/// An existing entity was updated in place (same `ObjectId` preserved).
|
||||
Updated(ObjectId),
|
||||
/// Entities were deleted; carries the deleted ids (one for `Delete`, N for `DeleteMany`).
|
||||
Deleted(Vec<ObjectId>),
|
||||
/// Many entities were created (bulk `CreateMany`); carries all fresh ids in order.
|
||||
NewIds(Vec<ObjectId>),
|
||||
}
|
||||
|
||||
impl OpOutcome {
|
||||
/// The single fresh id, for ops that create exactly one entity.
|
||||
pub fn new_id(&self) -> Option<ObjectId> {
|
||||
match self {
|
||||
OpOutcome::NewId(id) => Some(*id),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
/// All fresh ids, for bulk creates.
|
||||
pub fn new_ids(&self) -> &[ObjectId] {
|
||||
match self {
|
||||
OpOutcome::NewIds(ids) => ids,
|
||||
OpOutcome::NewId(id) => std::slice::from_ref(id),
|
||||
_ => &[],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The per-request result (and the query-batch answer carrier).
|
||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize)]
|
||||
pub struct Receipt {
|
||||
/// Present for `EnvelopeBody::Op`; absent for pure queries.
|
||||
pub outcome: Option<OpOutcome>,
|
||||
/// One `QueryResult` per `Query` in a `Queries` batch (in order).
|
||||
pub query_results: Vec<QueryResult>,
|
||||
/// The geometry revision after this request (== before, for pure queries).
|
||||
pub new_revision: GeometryRevision,
|
||||
}
|
||||
Reference in new issue
Block a user