gtk-rs / gir

Tool to generate rust bindings and user API for glib-based libraries
https://gtk-rs.org/gir/book/
MIT License
236 stars 107 forks source link

Add configuration for exhaustive enums #1433

Closed sdroege closed 1 year ago

sdroege commented 1 year ago

This allows them to be represented as a plain i32 instead of a 5-byte big enum, which in turn allows direct casting between the C and Rust type and fitting the value into a register on 32 bit systems, or even a Result on 64 bit systems.


Example generated code for an example in GStreamer

#[must_use]
#[derive(Debug, Eq, PartialEq, Ord, PartialOrd, Hash, Clone, Copy)]
#[repr(i32)]
#[doc(alias = "GstFlowReturn")]
pub enum FlowReturn {
    #[doc(alias = "GST_FLOW_CUSTOM_SUCCESS_2")]
    CustomSuccess2 = ffi::GST_FLOW_CUSTOM_SUCCESS_2,
    #[doc(alias = "GST_FLOW_CUSTOM_SUCCESS_1")]
    CustomSuccess1 = ffi::GST_FLOW_CUSTOM_SUCCESS_1,
    #[doc(alias = "GST_FLOW_CUSTOM_SUCCESS")]
    CustomSuccess = ffi::GST_FLOW_CUSTOM_SUCCESS,
    #[doc(alias = "GST_FLOW_OK")]
    Ok = ffi::GST_FLOW_OK,
    #[doc(alias = "GST_FLOW_NOT_LINKED")]
    NotLinked = ffi::GST_FLOW_NOT_LINKED,
    #[doc(alias = "GST_FLOW_FLUSHING")]
    Flushing = ffi::GST_FLOW_FLUSHING,
    #[doc(alias = "GST_FLOW_EOS")]
    Eos = ffi::GST_FLOW_EOS,
    #[doc(alias = "GST_FLOW_NOT_NEGOTIATED")]
    NotNegotiated = ffi::GST_FLOW_NOT_NEGOTIATED,
    #[doc(alias = "GST_FLOW_ERROR")]
    Error = ffi::GST_FLOW_ERROR,
    #[doc(alias = "GST_FLOW_NOT_SUPPORTED")]
    NotSupported = ffi::GST_FLOW_NOT_SUPPORTED,
    #[doc(alias = "GST_FLOW_CUSTOM_ERROR")]
    CustomError = ffi::GST_FLOW_CUSTOM_ERROR,
    #[doc(alias = "GST_FLOW_CUSTOM_ERROR_1")]
    CustomError1 = ffi::GST_FLOW_CUSTOM_ERROR_1,
    #[doc(alias = "GST_FLOW_CUSTOM_ERROR_2")]
    CustomError2 = ffi::GST_FLOW_CUSTOM_ERROR_2,
}

#[doc(hidden)]
impl IntoGlib for FlowReturn {
    type GlibType = ffi::GstFlowReturn;

    #[inline]
    fn into_glib(self) -> ffi::GstFlowReturn {
        self as ffi::GstFlowReturn
    }
}

#[doc(hidden)]
impl FromGlib<ffi::GstFlowReturn> for FlowReturn {
    #[inline]
    unsafe fn from_glib(value: ffi::GstFlowReturn) -> Self {
        skip_assert_initialized!();

        debug_assert!([
            ffi::GST_FLOW_CUSTOM_SUCCESS_2,
            ffi::GST_FLOW_CUSTOM_SUCCESS_1,
            ffi::GST_FLOW_CUSTOM_SUCCESS,
            ffi::GST_FLOW_OK,
            ffi::GST_FLOW_NOT_LINKED,
            ffi::GST_FLOW_FLUSHING,
            ffi::GST_FLOW_EOS,
            ffi::GST_FLOW_NOT_NEGOTIATED,
            ffi::GST_FLOW_ERROR,
            ffi::GST_FLOW_NOT_SUPPORTED,
            ffi::GST_FLOW_CUSTOM_ERROR,
            ffi::GST_FLOW_CUSTOM_ERROR_1,
            ffi::GST_FLOW_CUSTOM_ERROR_2
        ]
        .contains(&value));
        std::mem::transmute(value)
    }
}

[...]
GuillaumeGomez commented 1 year ago

Sounds like a good idea. :+1: