Files
OneCAD-Draft/crates/ocs_plugin_api/src/ipc/server.rs
T
Sebastian e41086b058 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.
2026-09-06 00:15:27 +02:00

86 lines
3.2 KiB
Rust

//! Host-side IPC request handler.
use crate::host::HostApi;
use crate::ipc::protocol::{PluginRequest, PluginResponse};
/// Apply one plugin request to the host's `HostApi` implementation.
///
/// `on_start_interactive` is called when the plugin starts an interactive
/// command; the host should install an adapter that sends
/// `HostRequest::InteractiveEvent` back to the plugin process.
pub fn handle_plugin_request(
host: &mut dyn HostApi,
req: PluginRequest,
on_start_interactive: &mut dyn FnMut(u64),
) -> PluginResponse {
use PluginRequest::*;
match req {
PushInfo(msg) => {
host.push_info(&msg);
PluginResponse::Ok
}
PushOutput(msg) => {
host.push_output(&msg);
PluginResponse::Ok
}
PushError(msg) => {
host.push_error(&msg);
PluginResponse::Ok
}
AddEntity(entity) => PluginResponse::Handle(host.add_entity(entity)),
AddEntities(entities) => PluginResponse::Handles(host.add_entities(entities)),
UpdateEntity(entity) => PluginResponse::Bool(host.update_entity(entity)),
RemoveEntity { handle } => PluginResponse::Bool(host.remove_entity(handle)),
BumpGeometry => {
host.bump_geometry();
PluginResponse::Ok
}
ReadRecord { handle, app_name } => {
PluginResponse::Record(host.read_record(handle, &app_name).cloned())
}
WriteRecord { handle, record } => PluginResponse::Bool(host.write_record(handle, record)),
RemoveRecord { handle, app_name } => {
PluginResponse::Bool(host.remove_record(handle, &app_name))
}
PushUndo { label } => {
host.push_undo(&label);
PluginResponse::Ok
}
SetDirty => {
host.set_dirty();
PluginResponse::Ok
}
StartInteractive { command_id } => {
on_start_interactive(command_id);
PluginResponse::Ok
}
DocumentSnapshot => PluginResponse::Document(Box::new(host.document().clone())),
OpenDocumentView => match host.document_view() {
Some(info) => PluginResponse::DocumentView {
path: info.path,
version: info.version,
},
None => PluginResponse::Error("shared document view unavailable".to_string()),
},
OpenDocumentViewV4 { tab_id } => match host.document_view_v4(tab_id) {
Some(info) => PluginResponse::DocumentViewV4 {
path: info.path,
version: info.version,
},
None => PluginResponse::Error("V4 shared document view unavailable".to_string()),
},
CloseDocumentViewV4 { tab_id } => {
host.close_document_view_v4(tab_id);
PluginResponse::Ok
}
GetTabId => PluginResponse::TabId(host.tab_id()),
DocumentPath { tab_id } => PluginResponse::DocumentPath(
host.document_path(tab_id).map(|path| path.into_os_string()),
),
DocApiRequest { tab_id, bytes } => match host.doc_api_dispatch(tab_id, &bytes) {
Ok(bytes) => PluginResponse::DocApiResponse { bytes },
Err(msg) => PluginResponse::Error(msg),
},
}
}