forked from 1b-agent/opencadstudio-upstream
#249 — plugin XDATA written via write_record survived only in memory: the acadrust DWG writer dropped ExtendedData::records on save. Bump acadrust to e88a9a6 (records now encode to EED and decode back on read) and fix the host side that fed it: - ensure_app_id allocates a real APPID handle; a null handle serializes as 0 and the EED reference can't resolve, so the XDATA vanished on reopen. - write_record / remove_record drop stale raw_dwg_eed for the target app so an edit made after a save/reopen wins over the pre-edit bytes. #250 — out-of-process plugins got a throwaway document_mut() snapshot, so edits to existing entities were silently discarded and deletion wasn't expressible at all. Add the missing mutation surface: - UpdateEntity / RemoveEntity IPC requests + HostApi::update_entity / remove_entity (default in-process impls, RPC overrides on the client that invalidate the stale document cache). - Scene::update_entity replaces the entity in place, preserving its handle and owning block, and reseeds only its derived caches; remove reuses the cache-coherent erase_entities (which also honours layer locks). - document_mut() is documented as a local-only snapshot out-of-process. Co-Authored-By: Claude Opus 4.8 <[email protected]>
66 lines
2.3 KiB
Rust
66 lines
2.3 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)),
|
|
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(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()),
|
|
},
|
|
}
|
|
}
|