Add support for tagged enums that turn into structs.

This happens when the tags are separated. In this case the output is slightly
different since the tag is not part of the struct body, so we need the top-level
serializer to write the tag type.
This commit is contained in:
Kartikaya Gupta
2020-09-29 22:41:16 -04:00
committed by Emilio Cobos Álvarez
parent c5c17403b4
commit 2be47c88e6
9 changed files with 234 additions and 10 deletions
+6 -3
View File
@@ -803,24 +803,27 @@ impl Source for Enum {
.variants
.iter()
.map(|x| {
let tag_str = format!("\"{}\"", x.export_name);
if let VariantBody::Body { ref name, .. } = x.body {
format!(
"case {}::{}::{}: {} << {}.{}; break;",
"case {}::{}::{}: {} << {}{}{}.{}; break;",
self.export_name(),
enum_name,
x.export_name,
stream,
if separate_tag { &tag_str } else { "" },
if separate_tag { " << " } else { "" },
instance,
name,
)
} else {
format!(
"case {}::{}::{}: {} << \"{}\"; break;",
"case {}::{}::{}: {} << {}; break;",
self.export_name(),
enum_name,
x.export_name,
stream,
x.export_name,
tag_str,
)
}
})
+25 -1
View File
@@ -48,4 +48,28 @@ typedef union F {
Bar_Body bar;
} F;
void root(A a, B b, C c, D d, F f);
enum H_Tag {
Hello,
There,
Everyone,
};
typedef uint8_t H_Tag;
typedef struct Hello_Body {
int16_t _0;
} Hello_Body;
typedef struct There_Body {
uint8_t x;
int16_t y;
} There_Body;
typedef struct H {
H_Tag tag;
union {
Hello_Body hello;
There_Body there;
};
} H;
void root(A a, B b, C c, D d, F f, H h);
@@ -60,11 +60,41 @@ typedef union F {
Bar_Body bar;
} F;
enum H_Tag
#ifdef __cplusplus
: uint8_t
#endif // __cplusplus
{
Hello,
There,
Everyone,
};
#ifndef __cplusplus
typedef uint8_t H_Tag;
#endif // __cplusplus
typedef struct Hello_Body {
int16_t _0;
} Hello_Body;
typedef struct There_Body {
uint8_t x;
int16_t y;
} There_Body;
typedef struct H {
H_Tag tag;
union {
Hello_Body hello;
There_Body there;
};
} H;
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void root(A a, B b, C c, D d, F f);
void root(A a, B b, C c, D d, F f, H h);
#ifdef __cplusplus
} // extern "C"
+25 -1
View File
@@ -48,4 +48,28 @@ typedef union {
Bar_Body bar;
} F;
void root(A a, B b, C c, D d, F f);
enum H_Tag {
Hello,
There,
Everyone,
};
typedef uint8_t H_Tag;
typedef struct {
int16_t _0;
} Hello_Body;
typedef struct {
uint8_t x;
int16_t y;
} There_Body;
typedef struct {
H_Tag tag;
union {
Hello_Body hello;
There_Body there;
};
} H;
void root(A a, B b, C c, D d, F f, H h);
+31 -1
View File
@@ -60,11 +60,41 @@ typedef union {
Bar_Body bar;
} F;
enum H_Tag
#ifdef __cplusplus
: uint8_t
#endif // __cplusplus
{
Hello,
There,
Everyone,
};
#ifndef __cplusplus
typedef uint8_t H_Tag;
#endif // __cplusplus
typedef struct {
int16_t _0;
} Hello_Body;
typedef struct {
uint8_t x;
int16_t y;
} There_Body;
typedef struct {
H_Tag tag;
union {
Hello_Body hello;
There_Body there;
};
} H;
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void root(A a, B b, C c, D d, F f);
void root(A a, B b, C c, D d, F f, H h);
#ifdef __cplusplus
} // extern "C"
+51 -1
View File
@@ -101,8 +101,58 @@ union F {
Bar_Body bar;
};
struct H {
enum class Tag : uint8_t {
Hello,
There,
Everyone,
};
friend std::ostream& operator<<(std::ostream& stream, const Tag& instance) {
switch (instance) {
case H::Tag::Hello: stream << "Hello"; break;
case H::Tag::There: stream << "There"; break;
case H::Tag::Everyone: stream << "Everyone"; break;
}
return stream;
}
friend std::ostream& operator<<(std::ostream& stream, const H& instance) {
switch (instance.tag) {
case H::Tag::Hello: stream << "Hello" << instance.hello; break;
case H::Tag::There: stream << "There" << instance.there; break;
case H::Tag::Everyone: stream << "Everyone"; break;
}
return stream;
}
struct Hello_Body {
int16_t _0;
friend std::ostream& operator<<(std::ostream& stream, const Hello_Body& instance) {
return stream << "{ " << "_0=" << instance._0 << " }";
}
};
struct There_Body {
uint8_t x;
int16_t y;
friend std::ostream& operator<<(std::ostream& stream, const There_Body& instance) {
return stream << "{ " << "x=" << instance.x << ", "
<< "y=" << instance.y << " }";
}
};
Tag tag;
union {
Hello_Body hello;
There_Body there;
};
};
extern "C" {
void root(A a, B b, C c, D d, F f);
void root(A a, B b, C c, D d, F f, H h);
} // extern "C"
+25 -1
View File
@@ -48,4 +48,28 @@ union F {
struct Bar_Body bar;
};
void root(struct A a, struct B b, C c, struct D d, union F f);
enum H_Tag {
Hello,
There,
Everyone,
};
typedef uint8_t H_Tag;
struct Hello_Body {
int16_t _0;
};
struct There_Body {
uint8_t x;
int16_t y;
};
struct H {
H_Tag tag;
union {
struct Hello_Body hello;
struct There_Body there;
};
};
void root(struct A a, struct B b, C c, struct D d, union F f, struct H h);
+31 -1
View File
@@ -60,11 +60,41 @@ union F {
struct Bar_Body bar;
};
enum H_Tag
#ifdef __cplusplus
: uint8_t
#endif // __cplusplus
{
Hello,
There,
Everyone,
};
#ifndef __cplusplus
typedef uint8_t H_Tag;
#endif // __cplusplus
struct Hello_Body {
int16_t _0;
};
struct There_Body {
uint8_t x;
int16_t y;
};
struct H {
H_Tag tag;
union {
struct Hello_Body hello;
struct There_Body there;
};
};
#ifdef __cplusplus
extern "C" {
#endif // __cplusplus
void root(struct A a, struct B b, C c, struct D d, union F f);
void root(struct A a, struct B b, C c, struct D d, union F f, struct H h);
#ifdef __cplusplus
} // extern "C"
+9
View File
@@ -30,6 +30,14 @@ enum F {
Baz
}
/// cbindgen:derive-ostream
#[repr(C, u8)]
enum H {
Hello(i16),
There { x: u8, y: i16 },
Everyone
}
#[no_mangle]
pub extern "C" fn root(
a: A,
@@ -37,5 +45,6 @@ pub extern "C" fn root(
c: C,
d: D,
f: F,
h: H,
) { }