Skip to content

Commit c3dcc94

Browse files
authored
Implement ByteRepr for structs with ByteRepr fields (#122)
This allows memcpy'ing between structs
1 parent 08a11c2 commit c3dcc94

43 files changed

Lines changed: 978 additions & 61 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "converter/models/converter_refcount.h"
55

6+
#include <clang/AST/RecordLayout.h>
67
#include <clang/Basic/OperatorKinds.h>
78

89
#include <format>
@@ -497,10 +498,70 @@ void ConverterRefCount::AddDropTrait(const clang::CXXRecordDecl *decl) {
497498
StrCat("}");
498499
}
499500

501+
static bool recordImplementsByteRepr(const clang::RecordDecl *decl) {
502+
if (decl->isUnion()) {
503+
return false;
504+
}
505+
506+
// ByteRepr is only supported for user-defined structs that contain ByteRepr
507+
// fields.
508+
for (auto *f : decl->fields()) {
509+
auto qt = f->getType();
510+
if (qt->isEnumeralType()) {
511+
return false;
512+
}
513+
if (!qt->isIntegerType() && !qt->isFloatingType()) {
514+
return false;
515+
}
516+
}
517+
518+
return true;
519+
}
520+
500521
void ConverterRefCount::AddByteReprTrait(const clang::RecordDecl *decl) {
501522
auto struct_name = GetRecordName(decl);
523+
524+
if (!recordImplementsByteRepr(decl)) {
525+
StrCat(std::format("impl ByteRepr for {}", struct_name));
526+
PushBrace brace(*this);
527+
return;
528+
}
529+
502530
StrCat(std::format("impl ByteRepr for {}", struct_name));
503-
PushBrace brace(*this);
531+
PushBrace impl_brace(*this);
532+
533+
const auto &layout = ctx_.getASTRecordLayout(decl);
534+
535+
StrCat("fn to_bytes(&self, buf: &mut [u8])");
536+
{
537+
PushBrace fn_brace(*this);
538+
unsigned idx = 0;
539+
for (auto *field : decl->fields()) {
540+
auto byte_off = layout.getFieldOffset(idx) / 8;
541+
auto byte_size = ctx_.getTypeSize(field->getType()) / 8;
542+
StrCat(std::format("(*self.{}.borrow()).to_bytes(&mut buf[{}..{}]);",
543+
GetNamedDeclAsString(field), byte_off,
544+
byte_off + byte_size));
545+
++idx;
546+
}
547+
}
548+
549+
StrCat("fn from_bytes(buf: &[u8]) -> Self");
550+
{
551+
PushBrace fn_brace(*this);
552+
StrCat("Self");
553+
PushBrace lit_brace(*this);
554+
unsigned idx = 0;
555+
for (auto *field : decl->fields()) {
556+
auto byte_off = layout.getFieldOffset(idx) / 8;
557+
auto byte_size = ctx_.getTypeSize(field->getType()) / 8;
558+
StrCat(std::format(
559+
"{}: Rc::new(RefCell::new(<{}>::from_bytes(&buf[{}..{}]))),",
560+
GetNamedDeclAsString(field), Mapper::Map(field->getType()), byte_off,
561+
byte_off + byte_size));
562+
++idx;
563+
}
564+
}
504565
}
505566

506567
std::string
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
#include <assert.h>
2+
#include <stddef.h>
3+
#include <stdint.h>
4+
#include <string.h>
5+
6+
struct Entry {
7+
uint8_t bits;
8+
uint16_t value;
9+
};
10+
11+
int main(void) {
12+
struct Entry table[8] = {
13+
{1, 0x1111}, {2, 0x2222}, {3, 0x3333}, {4, 0x4444},
14+
{0, 0}, {0, 0}, {0, 0}, {0, 0},
15+
};
16+
size_t table_size = 4;
17+
18+
memcpy(&table[table_size], &table[0], table_size * sizeof(table[0]));
19+
20+
assert(table[4].bits == 1 && table[4].value == 0x1111);
21+
assert(table[5].bits == 2 && table[5].value == 0x2222);
22+
assert(table[6].bits == 3 && table[6].value == 0x3333);
23+
assert(table[7].bits == 4 && table[7].value == 0x4444);
24+
25+
return 0;
26+
}

tests/unit/out/refcount/addr_of_global.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,16 @@ impl Clone for Inner {
1818
this
1919
}
2020
}
21-
impl ByteRepr for Inner {}
21+
impl ByteRepr for Inner {
22+
fn to_bytes(&self, buf: &mut [u8]) {
23+
(*self.value.borrow()).to_bytes(&mut buf[0..4]);
24+
}
25+
fn from_bytes(buf: &[u8]) -> Self {
26+
Self {
27+
value: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
28+
}
29+
}
30+
}
2231
#[derive(Default)]
2332
pub struct Outer {
2433
pub p: Value<Ptr<Inner>>,

tests/unit/out/refcount/anonymous-struct.rs

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,18 @@ impl Clone for Outer_Named {
2020
this
2121
}
2222
}
23-
impl ByteRepr for Outer_Named {}
23+
impl ByteRepr for Outer_Named {
24+
fn to_bytes(&self, buf: &mut [u8]) {
25+
(*self.a.borrow()).to_bytes(&mut buf[0..4]);
26+
(*self.b.borrow()).to_bytes(&mut buf[4..8]);
27+
}
28+
fn from_bytes(buf: &[u8]) -> Self {
29+
Self {
30+
a: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
31+
b: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
32+
}
33+
}
34+
}
2435
#[derive(Default)]
2536
pub struct Outer_anon_0 {
2637
pub c: Value<i32>,
@@ -35,7 +46,18 @@ impl Clone for Outer_anon_0 {
3546
this
3647
}
3748
}
38-
impl ByteRepr for Outer_anon_0 {}
49+
impl ByteRepr for Outer_anon_0 {
50+
fn to_bytes(&self, buf: &mut [u8]) {
51+
(*self.c.borrow()).to_bytes(&mut buf[0..4]);
52+
(*self.d.borrow()).to_bytes(&mut buf[4..8]);
53+
}
54+
fn from_bytes(buf: &[u8]) -> Self {
55+
Self {
56+
c: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
57+
d: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
58+
}
59+
}
60+
}
3961
#[derive(Default)]
4062
pub struct Outer_anon_1 {
4163
pub g: Value<i32>,
@@ -50,7 +72,18 @@ impl Clone for Outer_anon_1 {
5072
this
5173
}
5274
}
53-
impl ByteRepr for Outer_anon_1 {}
75+
impl ByteRepr for Outer_anon_1 {
76+
fn to_bytes(&self, buf: &mut [u8]) {
77+
(*self.g.borrow()).to_bytes(&mut buf[0..4]);
78+
(*self.h.borrow()).to_bytes(&mut buf[4..8]);
79+
}
80+
fn from_bytes(buf: &[u8]) -> Self {
81+
Self {
82+
g: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
83+
h: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
84+
}
85+
}
86+
}
5487
#[derive(Default)]
5588
pub struct Outer_anon_2 {
5689
pub e: Value<i32>,
@@ -65,7 +98,18 @@ impl Clone for Outer_anon_2 {
6598
this
6699
}
67100
}
68-
impl ByteRepr for Outer_anon_2 {}
101+
impl ByteRepr for Outer_anon_2 {
102+
fn to_bytes(&self, buf: &mut [u8]) {
103+
(*self.e.borrow()).to_bytes(&mut buf[0..4]);
104+
(*self.f.borrow()).to_bytes(&mut buf[4..8]);
105+
}
106+
fn from_bytes(buf: &[u8]) -> Self {
107+
Self {
108+
e: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
109+
f: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
110+
}
111+
}
112+
}
69113
#[derive(Default)]
70114
pub struct Outer_anon_3_anon_0 {
71115
pub j: Value<i32>,
@@ -78,7 +122,16 @@ impl Clone for Outer_anon_3_anon_0 {
78122
this
79123
}
80124
}
81-
impl ByteRepr for Outer_anon_3_anon_0 {}
125+
impl ByteRepr for Outer_anon_3_anon_0 {
126+
fn to_bytes(&self, buf: &mut [u8]) {
127+
(*self.j.borrow()).to_bytes(&mut buf[0..4]);
128+
}
129+
fn from_bytes(buf: &[u8]) -> Self {
130+
Self {
131+
j: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
132+
}
133+
}
134+
}
82135
#[derive(Default)]
83136
pub struct Outer_anon_3_anon_1 {
84137
pub k: Value<i32>,
@@ -91,7 +144,16 @@ impl Clone for Outer_anon_3_anon_1 {
91144
this
92145
}
93146
}
94-
impl ByteRepr for Outer_anon_3_anon_1 {}
147+
impl ByteRepr for Outer_anon_3_anon_1 {
148+
fn to_bytes(&self, buf: &mut [u8]) {
149+
(*self.k.borrow()).to_bytes(&mut buf[0..4]);
150+
}
151+
fn from_bytes(buf: &[u8]) -> Self {
152+
Self {
153+
k: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
154+
}
155+
}
156+
}
95157
#[derive(Default)]
96158
pub struct Outer_anon_3 {
97159
pub i: Value<i32>,
@@ -211,7 +273,18 @@ fn main_0() -> i32 {
211273
this
212274
}
213275
}
214-
impl ByteRepr for anon_0 {};
276+
impl ByteRepr for anon_0 {
277+
fn to_bytes(&self, buf: &mut [u8]) {
278+
(*self.x.borrow()).to_bytes(&mut buf[0..4]);
279+
(*self.z.borrow()).to_bytes(&mut buf[4..8]);
280+
}
281+
fn from_bytes(buf: &[u8]) -> Self {
282+
Self {
283+
x: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
284+
z: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
285+
}
286+
}
287+
};
215288
let s: Value<anon_0> = Rc::new(RefCell::new(<anon_0>::default()));
216289
(*(*s.borrow()).x.borrow_mut()) = 1;
217290
(*(*s.borrow()).z.borrow_mut()) = 2;

tests/unit/out/refcount/anonymous-struct_c.rs

Lines changed: 80 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,35 +11,97 @@ pub struct Named {
1111
pub a: Value<i32>,
1212
pub b: Value<i32>,
1313
}
14-
impl ByteRepr for Named {}
14+
impl ByteRepr for Named {
15+
fn to_bytes(&self, buf: &mut [u8]) {
16+
(*self.a.borrow()).to_bytes(&mut buf[0..4]);
17+
(*self.b.borrow()).to_bytes(&mut buf[4..8]);
18+
}
19+
fn from_bytes(buf: &[u8]) -> Self {
20+
Self {
21+
a: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
22+
b: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
23+
}
24+
}
25+
}
1526
#[derive(Default)]
1627
pub struct Outer_anon_0 {
1728
pub c: Value<i32>,
1829
pub d: Value<i32>,
1930
}
20-
impl ByteRepr for Outer_anon_0 {}
31+
impl ByteRepr for Outer_anon_0 {
32+
fn to_bytes(&self, buf: &mut [u8]) {
33+
(*self.c.borrow()).to_bytes(&mut buf[0..4]);
34+
(*self.d.borrow()).to_bytes(&mut buf[4..8]);
35+
}
36+
fn from_bytes(buf: &[u8]) -> Self {
37+
Self {
38+
c: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
39+
d: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
40+
}
41+
}
42+
}
2143
#[derive(Default)]
2244
pub struct Outer_anon_1 {
2345
pub g: Value<i32>,
2446
pub h: Value<i32>,
2547
}
26-
impl ByteRepr for Outer_anon_1 {}
48+
impl ByteRepr for Outer_anon_1 {
49+
fn to_bytes(&self, buf: &mut [u8]) {
50+
(*self.g.borrow()).to_bytes(&mut buf[0..4]);
51+
(*self.h.borrow()).to_bytes(&mut buf[4..8]);
52+
}
53+
fn from_bytes(buf: &[u8]) -> Self {
54+
Self {
55+
g: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
56+
h: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
57+
}
58+
}
59+
}
2760
#[derive(Default)]
2861
pub struct Outer_anon_2 {
2962
pub e: Value<i32>,
3063
pub f: Value<i32>,
3164
}
32-
impl ByteRepr for Outer_anon_2 {}
65+
impl ByteRepr for Outer_anon_2 {
66+
fn to_bytes(&self, buf: &mut [u8]) {
67+
(*self.e.borrow()).to_bytes(&mut buf[0..4]);
68+
(*self.f.borrow()).to_bytes(&mut buf[4..8]);
69+
}
70+
fn from_bytes(buf: &[u8]) -> Self {
71+
Self {
72+
e: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
73+
f: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
74+
}
75+
}
76+
}
3377
#[derive(Default)]
3478
pub struct Outer_anon_3_anon_0 {
3579
pub j: Value<i32>,
3680
}
37-
impl ByteRepr for Outer_anon_3_anon_0 {}
81+
impl ByteRepr for Outer_anon_3_anon_0 {
82+
fn to_bytes(&self, buf: &mut [u8]) {
83+
(*self.j.borrow()).to_bytes(&mut buf[0..4]);
84+
}
85+
fn from_bytes(buf: &[u8]) -> Self {
86+
Self {
87+
j: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
88+
}
89+
}
90+
}
3891
#[derive(Default)]
3992
pub struct Outer_anon_3_anon_1 {
4093
pub k: Value<i32>,
4194
}
42-
impl ByteRepr for Outer_anon_3_anon_1 {}
95+
impl ByteRepr for Outer_anon_3_anon_1 {
96+
fn to_bytes(&self, buf: &mut [u8]) {
97+
(*self.k.borrow()).to_bytes(&mut buf[0..4]);
98+
}
99+
fn from_bytes(buf: &[u8]) -> Self {
100+
Self {
101+
k: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
102+
}
103+
}
104+
}
43105
#[derive(Default)]
44106
pub struct Outer_anon_3 {
45107
pub i: Value<i32>,
@@ -113,7 +175,18 @@ fn main_0() -> i32 {
113175
pub x: Value<i32>,
114176
pub z: Value<i32>,
115177
}
116-
impl ByteRepr for anon_0 {};
178+
impl ByteRepr for anon_0 {
179+
fn to_bytes(&self, buf: &mut [u8]) {
180+
(*self.x.borrow()).to_bytes(&mut buf[0..4]);
181+
(*self.z.borrow()).to_bytes(&mut buf[4..8]);
182+
}
183+
fn from_bytes(buf: &[u8]) -> Self {
184+
Self {
185+
x: Rc::new(RefCell::new(<i32>::from_bytes(&buf[0..4]))),
186+
z: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
187+
}
188+
}
189+
};
117190
let s: Value<anon_0> = <Value<anon_0>>::default();
118191
(*(*s.borrow()).x.borrow_mut()) = 1;
119192
(*(*s.borrow()).z.borrow_mut()) = 2;

0 commit comments

Comments
 (0)