node.jsrustasync-awaitwasm-bindgenrust-bindgen

Coerce anyhow::Error to NjError for node-bindgen


I want to wrap a rust function with node-bindgen to return a promise in JavaScript. The function in question returns an anyhow:Error.

This is my goofy attempt:

#[tokio::main]
#[node_bindgen]
async fn warprometo(offset: u32) -> Result<(), NjError> {
    Ok(crate::api::sync::coin_sync(0, true, offset, move |_height| {
        //
    }, &SYNC_CANCELED)
        .await?)
}

This results in:

error[E0277]: `?` couldn't convert the error to `NjError`
   --> hhanh00/zcash-sync/src/nodejs.rs:214:15
    |
214 |         .await?)
    |               ^ the trait `From<anyhow::Error>` is not implemented for `NjError`
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = help: the following implementations were found:
              <NjError as From<FromUtf8Error>>
              <NjError as From<NapiStatus>>
              <NjError as From<std::str::Utf8Error>>
    = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, anyhow::Error>>` for `Result<(), NjError>`

You can find this current misfire here. Thanks!

Some references I'm trying to work through to understand things:

https://docs.rs/anyhow/latest/anyhow/struct.Error.html

https://stackoverflow.com/a/62241599/177293

https://stackoverflow.com/a/53368681/177293

https://github.com/infinyon/node-bindgen/blob/master/examples/promise/src/lib.rs

hrm .. so close?


Solution

  • Ignoring the async parts, crate::api::sync::coin_sync is returning a Result<(),anyhow::Error> and warprometo is returning a Result<(),NjError>.

    The error message is telling you that there is no default conversion from anyhow::Error to NjError.

    The usual solution is to do the conversion yourself, and Result provides a method for doing this, map_err. The code could wrap the string form of the anyhow error into a NjError::Other - which would look something like this:

    #[tokio::main]
    #[node_bindgen]
    async fn warprometo(offset: u32) -> Result<(), NjError> {
        crate::api::sync::coin_sync(0, true, offset, move |_height| {
            //
        }, &SYNC_CANCELED)
            .await
            .map_err(|e| NjError::Other(format!("{}", e)))
    }