alef 0.25.13

Opinionated polyglot binding generator for Rust libraries
Documentation
// Trait-bridge support NIFs: round-trip the result of an Elixir-side trait
// method call back into the suspended Rust caller.
//
// The Rust bridge code for a generated plugin trait wrapper
// allocates a `tokio::sync::oneshot::channel`, stores the sender in
// `TRAIT_REPLY_CHANNELS` keyed by a monotonic `reply_id`, and sends a
// `{:trait_call, method, args_json, reply_id}` message to the Elixir
// GenServer that owns the plugin implementation. Without the two NIFs
// below the receiving side has no way to deliver the reply back, so every
// bridge call hangs forever and the registry's `register()` / drop /
// shutdown paths block under the DirtyCpu scheduler.
//
// `complete_trait_call/2` takes the JSON-encoded success result; `fail_trait_call/2`
// takes a string error reason. Both consume the sender; calling either a
// second time with the same `reply_id` is a no-op (the channel is gone).

#[rustler::nif]
pub fn complete_trait_call(reply_id: u64, result_json: String) -> rustler::types::atom::Atom {
    if let Ok(mut channels) = TRAIT_REPLY_CHANNELS.lock()
        && let Some(tx) = channels.remove(&reply_id)
    {
        let _ = tx.send(Ok(result_json));
    }
    rustler::types::atom::ok()
}

#[rustler::nif]
pub fn fail_trait_call(reply_id: u64, error_reason: String) -> rustler::types::atom::Atom {
    if let Ok(mut channels) = TRAIT_REPLY_CHANNELS.lock()
        && let Some(tx) = channels.remove(&reply_id)
    {
        let _ = tx.send(Err(error_reason));
    }
    rustler::types::atom::ok()
}