Skip to main content

DebugBindingBoundary

Trait DebugBindingBoundary 

Source
pub trait DebugBindingBoundary: Send + Sync {
    // Required method
    fn handle_to_debug(&self, handle: HandleId) -> Value;
}
Expand description

Render handles into JSON-shaped debug values.

Bindings that want to support Graph::describe_with_debug implement this trait alongside graphrefly_core::BindingBoundary. The two traits cover the two FFI surfaces:

  • BindingBoundary is the hot-path trait — invoked per fn-fire, per equals check, per handle refcount op. Bindings ALWAYS impl this.
  • DebugBindingBoundary is the cold-path trait — invoked once per named node per describe_with_debug call. Bindings impl this ONLY if they want their Graph::describe() output to surface value: T shapes instead of raw value: <u64> handles.

§Implementation guidance

For a typical binding that stores HashMap<HandleId, T> where T: Serialize, the implementation is one line:

impl DebugBindingBoundary for MyBinding {
    fn handle_to_debug(&self, h: HandleId) -> serde_json::Value {
        self.values.borrow_mut().get(&h)
            .map(|v| serde_json::to_value(v).unwrap_or(serde_json::Value::Null))
            .unwrap_or(serde_json::Value::Null)
    }
}

For value types that don’t implement serde::Serialize (e.g., JS function handles in napi-rs), the binding can return a descriptor object like { "type": "function", "fn_id": 42 } or fall back to Value::String(format!("<opaque:{h:?}>")).

§Thread safety

Send + Sync per the same rationale as BindingBoundary: the Core dispatcher may be cloned across threads, so any binding it holds must also be thread-safe.

Required Methods§

Source

fn handle_to_debug(&self, handle: HandleId) -> Value

Render handle as a JSON value. Implementations typically look the handle up in the binding’s value registry and serialize via serde_json::to_value(&value). Return serde_json::Value::Null for unknown / dangling handles (the call may race with concurrent release_handle finalizers).

Implementors§