Open BatmanAoD opened 7 months ago
@BatmanAoD How feasible is it to implement this feature with uniffi-rs
?
I've been using serde-repr for C-like enums and would like to see how I can generate their bindings for other languages, currently Swift.
@setoelkahfi Sorry, I don't know; I'm not a UniFFI contributor, just a user.
I'm not really sure what's requested here. How do you see this being relevant for UniFFI? What would it look like on the Kotlin/Swift/Python side to use this?
@BatmanAoD, no worries.
@badboy TLDR: Never mind. I'll change my implementation, and this request is no longer relevant.
I have a separate ErrorCode
enum representing my integer-based error_code
in an ErrorResponse
struct, like this:
#[derive(Serialize, Deserialize, Debug)]
#[tsync]
pub struct ErrorResponse {
pub error_code: ErrorCode,
pub message: String,
}
#[repr(i32)]
#[derive(Serialize_repr, Deserialize_repr, Debug, EnumIter)]
#[tsync]
pub enum ErrorCode {
Unknown = 0,
// User-defined error codes begin from 1000
UserNotFound = 1000,
// Rest of the codes
Then I realized I'd not be able to use the throwing errors, as explained here.
For Python, it would presumably generate an enum with FlagBoundary
set to either EJECT
(forcing the user to do type checks to handle unknown values) or KEEP
with the final variant being Unknown
. https://docs.python.org/3/library/enum.html#enum.FlagBoundary.EJECT
I don't know enough about Swift or Kotlin enums to say how they should handle this.
For Go, normal int newtypes already work this way.
Okay, I take back my word. I'd still want this feature. For a better explanation, see this Serde doc.
I changed my error structure to use a parent enum
instead of struct
, but I'll still need the int representation of the error code. In Swift, we use raw representable protocol to express this.
An enum with an integer raw value can be expressed like this:
enum ErrorCode: Int {
case parseError = 1,
case networkError = 2,
// etc
}
Does https://mozilla.github.io/uniffi-rs/latest/proc_macro/index.html#variant-discriminants help here? The discriminants are exposed to bindings in that scenario.
Yes, that's what I'm looking for, minus how to do it in a UDL file. At least I couldn't find it here.
@mhammond I don't understand how that helps, actually. My intent in this ticket is to provide a way to handle enum values from C (or other languages) that may actually be invalid variants. In Rust, even with repr
, this is immediate undefined behavior.
Fair enough - I got confused about who the OP was!
It's often useful to interoperate with C libraries that may return enum values; in this case you do not necessarily have a guarantee that the returned value is a valid variant, and it may be useful to preserve the original value, e.g. for round-tripping data.
It's simple enough to represent this in Rust:
...and then explicitly implement
From<u32> for Foo
andFrom<Foo> for u32
. Here's a library that provides a macro for defining enums in this way: https://github.com/cimbul/tartan-c-enumThis seems like something that would be useful for UniFFI to support as well.