Files
OneCAD-Draft/crates/ocs_doc_api/bindings/README.md
T

60 lines
2.9 KiB
Markdown

# 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:
```sh
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):
```rust
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.