Files
OneCAD-Draft/crates/ocs_doc_api/bindings

Language bindings

src/gen/binding_schema.json describes handle families, constructors, methods, arguments and operation/query mappings. build.rs derives it from spec/entities.toml. Its layouts section is manually maintained vocabulary; it does not contain everything needed to generate a bincode codec.

Generate and test the Python facade from the repository root:

python3 crates/ocs_doc_api/bindings/python/generate.py > /tmp/ocs_doc.py
python3 -m unittest discover -s crates/ocs_doc_api/bindings/python

The generated DocApi(transport, active_tab) expects a caller-supplied transport.apply(envelope) -> Receipt. It does not open a plugin connection. An envelope has version and a Python tuple ("Op", operation_dict) or ("Queries", [query_dict]). Enum payloads use externally tagged dictionaries, for example {"CreateSolid": {"Sphere": {"centre": [0, 0, 0], "radius": 2}}}. The bridge converts these objects to the Rust DTOs and bincode 1.3 wire format, sends DocApiRequest { tab_id, bytes }, and decodes Result<Receipt, ApiError>. Host plugin API version 6 and document envelope version 1 are required.

For Rust plugins compiled against ocs_doc_api with the doc_api_host feature, use the doc_api_for_host helper to build a typed DocApi from any ocs_plugin_api::host::HostApi that exposes a PluginRequestSender (out-of-process / worker-thread hosts):

use ocs_doc_api::doc_api_for_host;
use ocs_plugin_api::host::HostApi;

fn on_dispatch(host: &mut dyn HostApi) -> Option<()> {
    let doc_api = doc_api_for_host(host)?;
    let doc = doc_api.document(host.tab_id());
    let cube = doc.solids().create_cuboid([0.0; 3], [10.0; 3]).ok()?;
    // ...
    Some(())
}

In-process plugins should use DocApi::in_process(backend, tab_id) with a concrete DocApiBackend; doc_api_for_host returns None for hosts that do not expose a PluginRequestSender.

Decode receipt outcomes as {"NewId": 42} or {"NewIds": [42, 43]} and query results as externally tagged dictionaries such as {"Volume": 12.5}. The facade unwraps these into typed handles or values. Layer results use {"Layers": [...]} and {"EntityLayer": "WALLS"}. Layer properties (LayerInfo, LayerFlags, Color, LineWeight) appear as plain dictionaries in operation payloads, e.g. {"CreateLayer": {"name": "Walls", "flags": {"frozen": false, "locked": false, "frozen_in_new_viewport": false, "off": false}, "color": {"Index": 7}, "line_type": "Continuous", "line_weight": {"Default": null}, "plot_style": "", "is_plottable": true}}. XDATA and XRECORD payloads appear as nested externally tagged dictionaries (e.g. {"XData": {"application_name": ..., "values": [...]}} or {"XRecord": {"name": ..., "entries": [...]}}). The bridge must raise an exception for an error response. Transport binding determines the tab; requesting another tab or combining typed handles from different documents raises an error.