-
Notifications
You must be signed in to change notification settings - Fork 360
Description
I'd like to be able to mark unions that should be anonymous. As an example:
use core::mem::ManuallyDrop;
/// cbindgen:prefix-with-name=false
/// cbindgen:rename-all=ScreamingSnakeCase
#[repr(C)]
pub enum ResultTag {
ResultOk,
ResultErr,
}
/// cbindgen:make-anonymous=true
#[repr(C)]
pub union ResultValue<T, E> {
pub ok: ManuallyDrop<T>,
pub err: ManuallyDrop<E>,
}
#[repr(C)]
pub struct Result<T, E> {
pub tag: ResultTag,
// alternatively, it could go at the usage site
// instead of the definition site.
pub value: ResultValue<T, E>,
}
#[no_mangle]
pub unsafe extern "C" fn result() -> Result<usize, *const u8> {
todo!()
}Could generate this, depending on settings:
typedef enum ResultTag {
RESULT_OK,
RESULT_ERR,
} ResultTag;
typedef struct Result_usize_______u8 {
enum ResultTag tag;
union {
size_t ok;
const uint8_t *err;
} value;
} Result_usize_______u8;
struct Result_usize_______u8 result(void);To some degree, this is an alternative to unifying generic tags (which has been difficult to get all edges right). I hope the implementation is simpler because cbindgen can already emit an anonymous union, as it already does it for enums:
#[repr(C)]
pub enum Result<T, E> {
Ok(T),
Err(E),
}typedef enum Result_usize_______u8_Tag {
Ok_usize_______u8,
Err_usize_______u8,
} Result_usize_______u8_Tag;
typedef struct Result_usize_______u8 {
Result_usize_______u8_Tag tag;
union {
struct {
size_t ok;
};
struct {
const uint8_t *err;
};
};
} Result_usize_______u8;But this isn't only about generic types. There may be value in generating anonymous structs as well. For instance, I see anonymous structs and unions in C code fairly regularly, so wanting match the same API with a new implementation written in Rust seems like it would be valuable. PHP does this kind of thing with both structs and unions:
struct _zval_struct {
zend_value value; /* value */
union {
uint32_t type_info;
struct {
ZEND_ENDIAN_LOHI_3(
uint8_t type, /* active type */
uint8_t type_flags,
union {
uint16_t extra; /* not further specified */
} u)
} v;
} u1;
union {
uint32_t next; /* hash collision chain */
uint32_t cache_slot; /* cache slot (for RECV_INIT) */
uint32_t opline_num; /* opline number (for FAST_CALL) */
uint32_t lineno; /* line number (for ast nodes) */
uint32_t num_args; /* arguments number for EX(This) */
uint32_t fe_pos; /* foreach position */
uint32_t fe_iter_idx; /* foreach iterator index */
uint32_t guard; /* recursion and single property guard */
uint32_t constant_flags; /* constant flags */
uint32_t extra; /* not further specified */
} u2;
};But I would at least like to be able to do this for unions, as many unions are anonymous today and are very convenient this way.