Skip to content

Commit a79e291

Browse files
committed
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.
1 parent a31e870 commit a79e291

File tree

9 files changed

+234
-10
lines changed

9 files changed

+234
-10
lines changed

src/bindgen/ir/enumeration.rs

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -797,24 +797,27 @@ impl Source for Enum {
797797
.variants
798798
.iter()
799799
.map(|x| {
800+
let tag_str = format!("\"{}\"", x.export_name);
800801
if let VariantBody::Body { ref name, .. } = x.body {
801802
format!(
802-
"case {}::{}::{}: {} << {}.{}; break;",
803+
"case {}::{}::{}: {} << {}{}{}.{}; break;",
803804
self.export_name(),
804805
enum_name,
805806
x.export_name,
806807
stream,
808+
if separate_tag { &tag_str } else { "" },
809+
if separate_tag { " << " } else { "" },
807810
instance,
808811
name,
809812
)
810813
} else {
811814
format!(
812-
"case {}::{}::{}: {} << \"{}\"; break;",
815+
"case {}::{}::{}: {} << {}; break;",
813816
self.export_name(),
814817
enum_name,
815818
x.export_name,
816819
stream,
817-
x.export_name,
820+
tag_str,
818821
)
819822
}
820823
})

tests/expectations/both/derive_ostream.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,28 @@ typedef union F {
4848
Bar_Body bar;
4949
} F;
5050

51-
void root(A a, B b, C c, D d, F f);
51+
enum H_Tag {
52+
Hello,
53+
There,
54+
Everyone,
55+
};
56+
typedef uint8_t H_Tag;
57+
58+
typedef struct Hello_Body {
59+
int16_t _0;
60+
} Hello_Body;
61+
62+
typedef struct There_Body {
63+
uint8_t x;
64+
int16_t y;
65+
} There_Body;
66+
67+
typedef struct H {
68+
H_Tag tag;
69+
union {
70+
Hello_Body hello;
71+
There_Body there;
72+
};
73+
} H;
74+
75+
void root(A a, B b, C c, D d, F f, H h);

tests/expectations/both/derive_ostream.compat.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,41 @@ typedef union F {
6060
Bar_Body bar;
6161
} F;
6262

63+
enum H_Tag
64+
#ifdef __cplusplus
65+
: uint8_t
66+
#endif // __cplusplus
67+
{
68+
Hello,
69+
There,
70+
Everyone,
71+
};
72+
#ifndef __cplusplus
73+
typedef uint8_t H_Tag;
74+
#endif // __cplusplus
75+
76+
typedef struct Hello_Body {
77+
int16_t _0;
78+
} Hello_Body;
79+
80+
typedef struct There_Body {
81+
uint8_t x;
82+
int16_t y;
83+
} There_Body;
84+
85+
typedef struct H {
86+
H_Tag tag;
87+
union {
88+
Hello_Body hello;
89+
There_Body there;
90+
};
91+
} H;
92+
6393
#ifdef __cplusplus
6494
extern "C" {
6595
#endif // __cplusplus
6696

67-
void root(A a, B b, C c, D d, F f);
97+
void root(A a, B b, C c, D d, F f, H h);
6898

6999
#ifdef __cplusplus
70100
} // extern "C"

tests/expectations/derive_ostream.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,28 @@ typedef union {
4848
Bar_Body bar;
4949
} F;
5050

51-
void root(A a, B b, C c, D d, F f);
51+
enum H_Tag {
52+
Hello,
53+
There,
54+
Everyone,
55+
};
56+
typedef uint8_t H_Tag;
57+
58+
typedef struct {
59+
int16_t _0;
60+
} Hello_Body;
61+
62+
typedef struct {
63+
uint8_t x;
64+
int16_t y;
65+
} There_Body;
66+
67+
typedef struct {
68+
H_Tag tag;
69+
union {
70+
Hello_Body hello;
71+
There_Body there;
72+
};
73+
} H;
74+
75+
void root(A a, B b, C c, D d, F f, H h);

tests/expectations/derive_ostream.compat.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,41 @@ typedef union {
6060
Bar_Body bar;
6161
} F;
6262

63+
enum H_Tag
64+
#ifdef __cplusplus
65+
: uint8_t
66+
#endif // __cplusplus
67+
{
68+
Hello,
69+
There,
70+
Everyone,
71+
};
72+
#ifndef __cplusplus
73+
typedef uint8_t H_Tag;
74+
#endif // __cplusplus
75+
76+
typedef struct {
77+
int16_t _0;
78+
} Hello_Body;
79+
80+
typedef struct {
81+
uint8_t x;
82+
int16_t y;
83+
} There_Body;
84+
85+
typedef struct {
86+
H_Tag tag;
87+
union {
88+
Hello_Body hello;
89+
There_Body there;
90+
};
91+
} H;
92+
6393
#ifdef __cplusplus
6494
extern "C" {
6595
#endif // __cplusplus
6696

67-
void root(A a, B b, C c, D d, F f);
97+
void root(A a, B b, C c, D d, F f, H h);
6898

6999
#ifdef __cplusplus
70100
} // extern "C"

tests/expectations/derive_ostream.cpp

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -101,8 +101,58 @@ union F {
101101
Bar_Body bar;
102102
};
103103

104+
struct H {
105+
enum class Tag : uint8_t {
106+
Hello,
107+
There,
108+
Everyone,
109+
};
110+
111+
friend std::ostream& operator<<(std::ostream& stream, const Tag& instance) {
112+
switch (instance) {
113+
case H::Tag::Hello: stream << "Hello"; break;
114+
case H::Tag::There: stream << "There"; break;
115+
case H::Tag::Everyone: stream << "Everyone"; break;
116+
}
117+
return stream;
118+
}
119+
120+
friend std::ostream& operator<<(std::ostream& stream, const H& instance) {
121+
switch (instance.tag) {
122+
case H::Tag::Hello: stream << "Hello" << instance.hello; break;
123+
case H::Tag::There: stream << "There" << instance.there; break;
124+
case H::Tag::Everyone: stream << "Everyone"; break;
125+
}
126+
return stream;
127+
}
128+
129+
struct Hello_Body {
130+
int16_t _0;
131+
132+
friend std::ostream& operator<<(std::ostream& stream, const Hello_Body& instance) {
133+
return stream << "{ " << "_0=" << instance._0 << " }";
134+
}
135+
};
136+
137+
struct There_Body {
138+
uint8_t x;
139+
int16_t y;
140+
141+
friend std::ostream& operator<<(std::ostream& stream, const There_Body& instance) {
142+
return stream << "{ " << "x=" << instance.x << ", "
143+
<< "y=" << instance.y << " }";
144+
}
145+
};
146+
147+
Tag tag;
148+
union {
149+
Hello_Body hello;
150+
There_Body there;
151+
};
152+
};
153+
104154
extern "C" {
105155

106-
void root(A a, B b, C c, D d, F f);
156+
void root(A a, B b, C c, D d, F f, H h);
107157

108158
} // extern "C"

tests/expectations/tag/derive_ostream.c

Lines changed: 25 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,4 +48,28 @@ union F {
4848
struct Bar_Body bar;
4949
};
5050

51-
void root(struct A a, struct B b, C c, struct D d, union F f);
51+
enum H_Tag {
52+
Hello,
53+
There,
54+
Everyone,
55+
};
56+
typedef uint8_t H_Tag;
57+
58+
struct Hello_Body {
59+
int16_t _0;
60+
};
61+
62+
struct There_Body {
63+
uint8_t x;
64+
int16_t y;
65+
};
66+
67+
struct H {
68+
H_Tag tag;
69+
union {
70+
struct Hello_Body hello;
71+
struct There_Body there;
72+
};
73+
};
74+
75+
void root(struct A a, struct B b, C c, struct D d, union F f, struct H h);

tests/expectations/tag/derive_ostream.compat.c

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,11 +60,41 @@ union F {
6060
struct Bar_Body bar;
6161
};
6262

63+
enum H_Tag
64+
#ifdef __cplusplus
65+
: uint8_t
66+
#endif // __cplusplus
67+
{
68+
Hello,
69+
There,
70+
Everyone,
71+
};
72+
#ifndef __cplusplus
73+
typedef uint8_t H_Tag;
74+
#endif // __cplusplus
75+
76+
struct Hello_Body {
77+
int16_t _0;
78+
};
79+
80+
struct There_Body {
81+
uint8_t x;
82+
int16_t y;
83+
};
84+
85+
struct H {
86+
H_Tag tag;
87+
union {
88+
struct Hello_Body hello;
89+
struct There_Body there;
90+
};
91+
};
92+
6393
#ifdef __cplusplus
6494
extern "C" {
6595
#endif // __cplusplus
6696

67-
void root(struct A a, struct B b, C c, struct D d, union F f);
97+
void root(struct A a, struct B b, C c, struct D d, union F f, struct H h);
6898

6999
#ifdef __cplusplus
70100
} // extern "C"

tests/rust/derive_ostream.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,12 +30,21 @@ enum F {
3030
Baz
3131
}
3232

33+
/// cbindgen:derive-ostream
34+
#[repr(C, u8)]
35+
enum H {
36+
Hello(i16),
37+
There { x: u8, y: i16 },
38+
Everyone
39+
}
40+
3341
#[no_mangle]
3442
pub extern "C" fn root(
3543
a: A,
3644
b: B,
3745
c: C,
3846
d: D,
3947
f: F,
48+
h: H,
4049
) { }
4150

0 commit comments

Comments
 (0)