Skip to content

Commit 9080709

Browse files
committed
Add ByteRepr for enums
1 parent e9896d2 commit 9080709

22 files changed

Lines changed: 304 additions & 7 deletions

cpp2rust/converter/converter.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3154,6 +3154,7 @@ bool Converter::VisitEnumDecl(clang::EnumDecl *decl) {
31543154

31553155
AddFromImpl(decl);
31563156
AddIncDecImpls(decl);
3157+
AddByteReprTrait(decl);
31573158
return false;
31583159
}
31593160

@@ -3936,6 +3937,8 @@ void Converter::EmitDefaultStructLiteral(const clang::RecordDecl *decl) {
39363937

39373938
void Converter::AddByteReprTrait(const clang::RecordDecl *decl) {}
39383939

3940+
void Converter::AddByteReprTrait(const clang::EnumDecl *decl) {}
3941+
39393942
void Converter::ConvertUnsignedArithBinaryOperator(clang::BinaryOperator *op,
39403943
clang::Expr *expr) {
39413944
StrCat(token::kDot);

cpp2rust/converter/converter.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -539,6 +539,8 @@ class Converter : public clang::RecursiveASTVisitor<Converter> {
539539

540540
virtual void AddByteReprTrait(const clang::RecordDecl *decl);
541541

542+
virtual void AddByteReprTrait(const clang::EnumDecl *decl);
543+
542544
virtual void
543545
ConvertUnsignedArithBinaryOperator(clang::BinaryOperator *binary_operator,
544546
clang::Expr *expr);

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 13 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -510,10 +510,8 @@ static bool recordImplementsByteRepr(const clang::RecordDecl *decl) {
510510
// fields.
511511
for (auto *f : decl->fields()) {
512512
auto qt = f->getType();
513-
if (qt->isEnumeralType()) {
514-
return false;
515-
}
516-
if (!qt->isIntegerType() && !qt->isFloatingType()) {
513+
if (!qt->isIntegerType() && !qt->isFloatingType() &&
514+
!qt->isEnumeralType()) {
517515
return false;
518516
}
519517
}
@@ -567,6 +565,17 @@ void ConverterRefCount::AddByteReprTrait(const clang::RecordDecl *decl) {
567565
}
568566
}
569567

568+
void ConverterRefCount::AddByteReprTrait(const clang::EnumDecl *decl) {
569+
auto name = GetRecordName(decl);
570+
StrCat(std::format("impl ByteRepr for {}", name));
571+
PushBrace impl_brace(*this);
572+
StrCat(
573+
"fn to_bytes(&self, buf: &mut [u8]) { (*self as i32).to_bytes(buf); }");
574+
StrCat(std::format("fn from_bytes(buf: &[u8]) -> Self {{ "
575+
"<{}>::from(i32::from_bytes(buf)) }}",
576+
name));
577+
}
578+
570579
std::string
571580
ConverterRefCount::GetSelfMaybeWithMut(const clang::CXXMethodDecl *decl) {
572581
return "&self";

cpp2rust/converter/models/converter_refcount.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,8 @@ class ConverterRefCount final : public Converter {
3939

4040
void AddByteReprTrait(const clang::RecordDecl *decl) override;
4141

42+
void AddByteReprTrait(const clang::EnumDecl *decl) override;
43+
4244
void AddDefaultTrait(const clang::RecordDecl *decl) override;
4345

4446
void AddDefaultTraitForUnion(const clang::RecordDecl *decl) override;

tests/multi-file/cross_tu_anon_enum_collision/out/refcount/cross_tu_anon_enum_collision.rs

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ impl From<i32> for anon_0 {
2020
}
2121
}
2222
libcc2rs::impl_enum_inc_dec!(anon_0);
23+
impl ByteRepr for anon_0 {
24+
fn to_bytes(&self, buf: &mut [u8]) {
25+
(*self as i32).to_bytes(buf);
26+
}
27+
fn from_bytes(buf: &[u8]) -> Self {
28+
<anon_0>::from(i32::from_bytes(buf))
29+
}
30+
}
2331
pub fn a_value_1() -> i32 {
2432
let x: Value<i32> = Rc::new(RefCell::new(0));
2533
(*x.borrow_mut()) |= (anon_0::ALPHA as i32);
@@ -47,6 +55,14 @@ impl From<i32> for anon_3 {
4755
}
4856
}
4957
libcc2rs::impl_enum_inc_dec!(anon_3);
58+
impl ByteRepr for anon_3 {
59+
fn to_bytes(&self, buf: &mut [u8]) {
60+
(*self as i32).to_bytes(buf);
61+
}
62+
fn from_bytes(buf: &[u8]) -> Self {
63+
<anon_3>::from(i32::from_bytes(buf))
64+
}
65+
}
5066
pub fn b_value_2() -> i32 {
5167
let x: Value<i32> = Rc::new(RefCell::new(0));
5268
(*x.borrow_mut()) |= (anon_3::BETA as i32);

tests/multi-file/cross_tu_tag_collision/out/refcount/cross_tu_tag_collision.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,14 @@ impl From<i32> for widget_enum {
5151
}
5252
}
5353
libcc2rs::impl_enum_inc_dec!(widget_enum);
54+
impl ByteRepr for widget_enum {
55+
fn to_bytes(&self, buf: &mut [u8]) {
56+
(*self as i32).to_bytes(buf);
57+
}
58+
fn from_bytes(buf: &[u8]) -> Self {
59+
<widget_enum>::from(i32::from_bytes(buf))
60+
}
61+
}
5462
pub fn b_value_1() -> i32 {
5563
let w: Value<widget_enum> = Rc::new(RefCell::new(widget_enum::WIDGET_C));
5664
return ((*w.borrow()) as i32).clone();

tests/ub/out/refcount/enum_out_of_range_cast.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ impl From<i32> for Color {
2424
}
2525
}
2626
libcc2rs::impl_enum_inc_dec!(Color);
27+
impl ByteRepr for Color {
28+
fn to_bytes(&self, buf: &mut [u8]) {
29+
(*self as i32).to_bytes(buf);
30+
}
31+
fn from_bytes(buf: &[u8]) -> Self {
32+
<Color>::from(i32::from_bytes(buf))
33+
}
34+
}
2735
pub fn main() {
2836
std::process::exit(main_0());
2937
}

tests/ub/out/refcount/enum_out_of_range_increment.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,14 @@ impl From<i32> for color {
2424
}
2525
}
2626
libcc2rs::impl_enum_inc_dec!(color);
27+
impl ByteRepr for color {
28+
fn to_bytes(&self, buf: &mut [u8]) {
29+
(*self as i32).to_bytes(buf);
30+
}
31+
fn from_bytes(buf: &[u8]) -> Self {
32+
<color>::from(i32::from_bytes(buf))
33+
}
34+
}
2735
pub fn main() {
2836
std::process::exit(main_0());
2937
}

tests/unit/out/refcount/anonymous_enum.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ impl From<i32> for anon_0 {
2222
}
2323
}
2424
libcc2rs::impl_enum_inc_dec!(anon_0);
25+
impl ByteRepr for anon_0 {
26+
fn to_bytes(&self, buf: &mut [u8]) {
27+
(*self as i32).to_bytes(buf);
28+
}
29+
fn from_bytes(buf: &[u8]) -> Self {
30+
<anon_0>::from(i32::from_bytes(buf))
31+
}
32+
}
2533
#[derive(Clone, Copy, PartialEq, Debug, Default)]
2634
enum anon_1 {
2735
#[default]
@@ -38,6 +46,14 @@ impl From<i32> for anon_1 {
3846
}
3947
}
4048
libcc2rs::impl_enum_inc_dec!(anon_1);
49+
impl ByteRepr for anon_1 {
50+
fn to_bytes(&self, buf: &mut [u8]) {
51+
(*self as i32).to_bytes(buf);
52+
}
53+
fn from_bytes(buf: &[u8]) -> Self {
54+
<anon_1>::from(i32::from_bytes(buf))
55+
}
56+
}
4157
#[derive(Default)]
4258
pub struct S {
4359
pub a: Value<i32>,
@@ -76,6 +92,14 @@ impl From<i32> for TdEnum {
7692
}
7793
}
7894
libcc2rs::impl_enum_inc_dec!(TdEnum);
95+
impl ByteRepr for TdEnum {
96+
fn to_bytes(&self, buf: &mut [u8]) {
97+
(*self as i32).to_bytes(buf);
98+
}
99+
fn from_bytes(buf: &[u8]) -> Self {
100+
<TdEnum>::from(i32::from_bytes(buf))
101+
}
102+
}
79103
#[derive(Clone, Copy, PartialEq, Debug, Default)]
80104
enum anon_2 {
81105
#[default]
@@ -92,6 +116,14 @@ impl From<i32> for anon_2 {
92116
}
93117
}
94118
libcc2rs::impl_enum_inc_dec!(anon_2);
119+
impl ByteRepr for anon_2 {
120+
fn to_bytes(&self, buf: &mut [u8]) {
121+
(*self as i32).to_bytes(buf);
122+
}
123+
fn from_bytes(buf: &[u8]) -> Self {
124+
<anon_2>::from(i32::from_bytes(buf))
125+
}
126+
}
95127
#[derive(Default)]
96128
pub struct WithAnonField {
97129
pub a: Value<i32>,
@@ -106,7 +138,18 @@ impl Clone for WithAnonField {
106138
this
107139
}
108140
}
109-
impl ByteRepr for WithAnonField {}
141+
impl ByteRepr for WithAnonField {
142+
fn to_bytes(&self, buf: &mut [u8]) {
143+
(*self.a.borrow()).to_bytes(&mut buf[0..4]);
144+
(*self.field.borrow()).to_bytes(&mut buf[4..8]);
145+
}
146+
fn from_bytes(buf: &[u8]) -> Self {
147+
Self {
148+
a: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
149+
field: Rc::new(RefCell::new(<anon_2>::from_bytes(&buf[4..8]))),
150+
}
151+
}
152+
}
110153
pub fn main() {
111154
std::process::exit(main_0());
112155
}
@@ -127,6 +170,14 @@ fn main_0() -> i32 {
127170
}
128171
}
129172
libcc2rs::impl_enum_inc_dec!(anon_3);
173+
impl ByteRepr for anon_3 {
174+
fn to_bytes(&self, buf: &mut [u8]) {
175+
(*self as i32).to_bytes(buf);
176+
}
177+
fn from_bytes(buf: &[u8]) -> Self {
178+
<anon_3>::from(i32::from_bytes(buf))
179+
}
180+
};
130181
assert!(((anon_0::FIRST_A as i32) != (anon_0::FIRST_B as i32)));
131182
assert!(((anon_1::SECOND_A as i32) != (anon_1::SECOND_B as i32)));
132183
assert!(((anon_3::THIRD_A as i32) != (anon_3::THIRD_B as i32)));

tests/unit/out/refcount/anonymous_enum_c.rs

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,14 @@ impl From<i32> for anon_0 {
2222
}
2323
}
2424
libcc2rs::impl_enum_inc_dec!(anon_0);
25+
impl ByteRepr for anon_0 {
26+
fn to_bytes(&self, buf: &mut [u8]) {
27+
(*self as i32).to_bytes(buf);
28+
}
29+
fn from_bytes(buf: &[u8]) -> Self {
30+
<anon_0>::from(i32::from_bytes(buf))
31+
}
32+
}
2533
#[derive(Clone, Copy, PartialEq, Debug, Default)]
2634
enum anon_1 {
2735
#[default]
@@ -38,6 +46,14 @@ impl From<i32> for anon_1 {
3846
}
3947
}
4048
libcc2rs::impl_enum_inc_dec!(anon_1);
49+
impl ByteRepr for anon_1 {
50+
fn to_bytes(&self, buf: &mut [u8]) {
51+
(*self as i32).to_bytes(buf);
52+
}
53+
fn from_bytes(buf: &[u8]) -> Self {
54+
<anon_1>::from(i32::from_bytes(buf))
55+
}
56+
}
4157
#[derive(Default)]
4258
pub struct S {
4359
pub a: Value<i32>,
@@ -68,6 +84,14 @@ impl From<i32> for TdEnum_enum {
6884
}
6985
}
7086
libcc2rs::impl_enum_inc_dec!(TdEnum_enum);
87+
impl ByteRepr for TdEnum_enum {
88+
fn to_bytes(&self, buf: &mut [u8]) {
89+
(*self as i32).to_bytes(buf);
90+
}
91+
fn from_bytes(buf: &[u8]) -> Self {
92+
<TdEnum_enum>::from(i32::from_bytes(buf))
93+
}
94+
}
7195
#[derive(Clone, Copy, PartialEq, Debug, Default)]
7296
enum anon_2 {
7397
#[default]
@@ -84,12 +108,31 @@ impl From<i32> for anon_2 {
84108
}
85109
}
86110
libcc2rs::impl_enum_inc_dec!(anon_2);
111+
impl ByteRepr for anon_2 {
112+
fn to_bytes(&self, buf: &mut [u8]) {
113+
(*self as i32).to_bytes(buf);
114+
}
115+
fn from_bytes(buf: &[u8]) -> Self {
116+
<anon_2>::from(i32::from_bytes(buf))
117+
}
118+
}
87119
#[derive(Default)]
88120
pub struct WithAnonField {
89121
pub a: Value<i32>,
90122
pub field: Value<anon_2>,
91123
}
92-
impl ByteRepr for WithAnonField {}
124+
impl ByteRepr for WithAnonField {
125+
fn to_bytes(&self, buf: &mut [u8]) {
126+
(*self.a.borrow()).to_bytes(&mut buf[0..4]);
127+
(*self.field.borrow()).to_bytes(&mut buf[4..8]);
128+
}
129+
fn from_bytes(buf: &[u8]) -> Self {
130+
Self {
131+
a: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
132+
field: Rc::new(RefCell::new(<anon_2>::from_bytes(&buf[4..8]))),
133+
}
134+
}
135+
}
93136
pub fn main() {
94137
std::process::exit(main_0());
95138
}
@@ -110,6 +153,14 @@ fn main_0() -> i32 {
110153
}
111154
}
112155
libcc2rs::impl_enum_inc_dec!(anon_3);
156+
impl ByteRepr for anon_3 {
157+
fn to_bytes(&self, buf: &mut [u8]) {
158+
(*self as i32).to_bytes(buf);
159+
}
160+
fn from_bytes(buf: &[u8]) -> Self {
161+
<anon_3>::from(i32::from_bytes(buf))
162+
}
163+
};
113164
assert!(((((anon_0::FIRST_A as i32) != (anon_0::FIRST_B as i32)) as i32) != 0));
114165
assert!(((((anon_1::SECOND_A as i32) != (anon_1::SECOND_B as i32)) as i32) != 0));
115166
assert!(((((anon_3::THIRD_A as i32) != (anon_3::THIRD_B as i32)) as i32) != 0));

0 commit comments

Comments
 (0)