Commit 905b9a09 authored by Ingvar Stepanyan's avatar Ingvar Stepanyan Committed by Ryan Hunt

Add support for repr(C) tagged enums too

parent 3b61c8ea
......@@ -62,16 +62,18 @@ impl Enum {
name: format!("{}_Body", variant.ident),
generic_params: GenericParams::default(),
fields: {
let mut res = vec![
(
let mut res = Vec::new();
if repr != Repr::C {
res.push((
"tag".to_string(),
Type::Path(GenericPath {
name: "Tag".to_string(),
generics: vec![],
}),
Documentation::none(),
),
];
));
}
for (i, field) in fields.iter().enumerate() {
if let Some(ty) = Type::load(&field.ty)? {
......@@ -88,7 +90,7 @@ impl Enum {
res
},
is_variant: true,
is_variant: repr != Repr::C,
tuple_struct: match variant.data {
syn::VariantData::Tuple(_) => true,
_ => false,
......@@ -158,12 +160,14 @@ impl Item for Enum {
if config.language == Language::C && self.tag.is_some() {
// it makes sense to always prefix Tag with type name in C
let new_tag = format!("{}_Tag", self.name);
for value in &mut self.values {
if let Some(ref mut body) = value.2 {
body.fields[0].1 = Type::Path(GenericPath {
name: new_tag.clone(),
generics: vec![],
});
if self.repr != Repr::C {
for value in &mut self.values {
if let Some(ref mut body) = value.2 {
body.fields[0].1 = Type::Path(GenericPath {
name: new_tag.clone(),
generics: vec![],
});
}
}
}
self.tag = Some(new_tag);
......@@ -209,6 +213,19 @@ impl Item for Enum {
impl Source for Enum {
fn write<F: Write>(&self, config: &Config, out: &mut SourceWriter<F>) {
let size = match self.repr {
Repr::C => None,
Repr::USize => Some("uintptr_t"),
Repr::U32 => Some("uint32_t"),
Repr::U16 => Some("uint16_t"),
Repr::U8 => Some("uint8_t"),
Repr::ISize => Some("intptr_t"),
Repr::I32 => Some("int32_t"),
Repr::I16 => Some("int16_t"),
Repr::I8 => Some("int8_t"),
_ => unreachable!(),
};
self.cfg.write_before(config, out);
self.documentation.write(config, out);
......@@ -216,7 +233,8 @@ impl Source for Enum {
let is_tagged = self.tag.is_some();
if is_tagged && config.language == Language::Cxx {
write!(out, "union {}", self.name);
out.write(if size.is_some() { "union " } else { "struct " });
write!(out, "{}", self.name);
out.open_brace();
}
......@@ -226,19 +244,6 @@ impl Source for Enum {
&self.name
};
let size = match self.repr {
Repr::C => None,
Repr::USize => Some("uintptr_t"),
Repr::U32 => Some("uint32_t"),
Repr::U16 => Some("uint16_t"),
Repr::U8 => Some("uint8_t"),
Repr::ISize => Some("intptr_t"),
Repr::I32 => Some("int32_t"),
Repr::I16 => Some("int16_t"),
Repr::I8 => Some("int8_t"),
_ => unreachable!(),
};
if config.language == Language::C {
if size.is_none() {
out.write("typedef enum");
......@@ -299,14 +304,26 @@ impl Source for Enum {
}
write!(out, "{} tag;", enum_name);
out.new_line();
for value in &self.values {
if size.is_none() {
out.write("union");
out.open_brace();
}
for (i, value) in self.values.iter().enumerate() {
if let Some(ref body) = value.2 {
out.new_line();
if i != 0 {
out.new_line();
}
write!(out, "{} {};", body.name, value.0);
}
}
if size.is_none() {
out.close_brace(true);
}
if config.language == Language::C {
out.close_brace(false);
write!(out, " {};", self.name);
......
......@@ -66,6 +66,29 @@ typedef union {
Bar_Body Bar;
} F;
typedef enum {
G_Foo = 0,
G_Bar = 1,
G_Baz = 2,
} G_Tag;
typedef struct {
int16_t _0;
} G_Foo_Body;
typedef struct {
uint8_t x;
int16_t y;
} G_Bar_Body;
typedef union {
G_Tag tag;
union {
G_Foo_Body G_Foo;
G_Bar_Body G_Bar;
};
} G;
typedef struct Opaque Opaque;
void root(Opaque *o, A a, B b, C c, D d, E e, F f);
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g);
......@@ -59,10 +59,33 @@ union F {
Bar_Body Bar;
};
struct G {
enum class Tag {
G_Foo = 0,
G_Bar = 1,
G_Baz = 2,
};
struct G_Foo_Body {
int16_t _0;
};
struct G_Bar_Body {
uint8_t x;
int16_t y;
};
Tag tag;
union {
G_Foo_Body G_Foo;
G_Bar_Body G_Bar;
};
};
struct Opaque;
extern "C" {
void root(Opaque *o, A a, B b, C c, D d, E e, F f);
void root(Opaque *o, A a, B b, C c, D d, E e, F f, G g);
} // extern "C"
......@@ -50,6 +50,14 @@ enum F {
Baz
}
/// cbindgen:prefix-with-name
#[repr(C)]
enum G {
Foo(i16),
Bar { x: u8, y: i16 },
Baz
}
#[no_mangle]
pub extern "C" fn root(
o: *mut Opaque,
......@@ -58,5 +66,6 @@ pub extern "C" fn root(
c: C,
d: D,
e: E,
f: F
f: F,
g: G
) { }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment