0

I am making Rust bindings for an existing proprietary C library. The library defines a fairly large enum containing possible status and error codes, i.e.:

enum RET_CODE
{
    STA_OK = 0,
    STA_SOME_CONDITION,
    STA_ANOTHER_CONDITION,
    /* ... more status codes ... */

    ERR_INTERNAL,
    ERR_SYSTEM,
    ERR_INPUT_OUTPUT,
    /* ... more than 100 other error codes ... */
};

Library functions return these RET_CODE values. Status codes start with STA_ and do not mean a failure; they signal various conditions. Error codes start with ERR_.

My idea is to split this enum into two Rust enums, StatusCode and ErrorCode, like that:

enum StatusCode {
    Ok = ffi::RET_CODE::STA_OK,
    SomeCondition = ffi::RET_CODE::SOME_CONDITION,
    AnotherCondition = ffi::RET_CODE::ANOTHER_CONDITION,
    // ...
}

enum ErrorCode {
    Internal = ffi::RET_CODE::ERR_INTERNAL,
    System = ffi::RET_CODE::ERR_SYSTEM,
    InputOutput = ffi::RET_CODE::ERR_INPUT_OUTPUT,
    // ...
}

Rust wrapper functions will then return std::result::Result<StatusCode, ErrorCode>. However, I do not want to define those Rust enums manually, since the status and error codes in the C library are subject to change, and it is quite likely that I will forget to update the Rust bindings. Modifying the C library is not an option.

Is it possible to use Rust macros (or something else) to produce those Rust enums from the single C API enum? It would be great to rename the variants as well (i.e. STA_SOME_CONDITION would become SomeCondition), but this could apparently be handled by bindgen's ParseCallbacks.

Roman Dmitrienko
  • 3,375
  • 3
  • 37
  • 48
  • Manually modifying the output of bindgen is allowed? – Shepmaster Nov 20 '19 at 14:45
  • @Shepmaster I'm using the bindgen library with build.rs. Modifying the output manually would not be feasible, I believe. – Roman Dmitrienko Nov 20 '19 at 14:55
  • If you cannot modify the output of bindgen, and bindgen doesn't give you the hooks you need, you appear to have no solution. See also [How do I apply a macro attribute to a function defined in a separate module?](https://stackoverflow.com/q/53364002/155423) – Shepmaster Nov 20 '19 at 15:01
  • 2
    You can generate another source code from your `build.rs`, by scanning either the `.h` or the `bindgen` output to find the enum variants and outputting your `StatusCode` and `ErrorCode` enums. – Jmb Nov 20 '19 at 15:39
  • @Jmb Thanks! I'll have to do that, apparently. Looks like I severely misunderstood the nature of the Rust macros :) – Roman Dmitrienko Nov 21 '19 at 09:49

0 Answers0