Skip to content

Commit 4b1deff

Browse files
authored
Add ByteRepr for unions (#212)
1 parent d82d983 commit 4b1deff

6 files changed

Lines changed: 95 additions & 8 deletions

File tree

cpp2rust/converter/converter_lib.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ bool TypeImplementsByteRepr(clang::QualType qt) {
213213
return false;
214214
}
215215
if (rd->isUnion()) {
216-
return false;
216+
return true;
217217
}
218218
for (const auto *field : rd->fields()) {
219219
if (!TypeImplementsByteRepr(field->getType())) {

cpp2rust/converter/models/converter_refcount.cpp

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -554,9 +554,20 @@ void ConverterRefCount::AddByteReprTrait(const clang::RecordDecl *decl) {
554554
return;
555555
}
556556

557-
StrCat(std::format("impl ByteRepr for {}", struct_name));
557+
StrCat("impl ByteRepr for ", struct_name);
558558
PushBrace impl_brace(*this);
559559

560+
if (decl->isUnion()) {
561+
StrCat(std::format("fn byte_size() -> usize {{ {} }}",
562+
ctx_.getTypeSize(ctx_.getCanonicalTagType(decl)) / 8));
563+
StrCat("fn to_bytes(&self, buf: &mut [u8]) { "
564+
"buf.copy_from_slice(&self.__bytes.borrow()); }");
565+
StrCat(std::format("fn from_bytes(buf: &[u8]) -> Self {{ {} {{ __bytes: "
566+
"Rc::new(RefCell::new(Box::from(buf))) }} }}",
567+
struct_name));
568+
return;
569+
}
570+
560571
const auto &layout = ctx_.getASTRecordLayout(decl);
561572

562573
StrCat(std::format("fn byte_size() -> usize {{ {} }}",

tests/unit/out/refcount/tag_vs_identifier_collision.rs

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -97,7 +97,19 @@ impl Default for point {
9797
}
9898
}
9999
}
100-
impl ByteRepr for point {}
100+
impl ByteRepr for point {
101+
fn byte_size() -> usize {
102+
4
103+
}
104+
fn to_bytes(&self, buf: &mut [u8]) {
105+
buf.copy_from_slice(&self.__bytes.borrow());
106+
}
107+
fn from_bytes(buf: &[u8]) -> Self {
108+
point {
109+
__bytes: Rc::new(RefCell::new(Box::from(buf))),
110+
}
111+
}
112+
}
101113
pub struct slot_union {
102114
__bytes: Value<Box<[u8]>>,
103115
}
@@ -123,7 +135,19 @@ impl Default for slot_union {
123135
}
124136
}
125137
}
126-
impl ByteRepr for slot_union {}
138+
impl ByteRepr for slot_union {
139+
fn byte_size() -> usize {
140+
4
141+
}
142+
fn to_bytes(&self, buf: &mut [u8]) {
143+
buf.copy_from_slice(&self.__bytes.borrow());
144+
}
145+
fn from_bytes(buf: &[u8]) -> Self {
146+
slot_union {
147+
__bytes: Rc::new(RefCell::new(Box::from(buf))),
148+
}
149+
}
150+
}
127151
#[derive(Clone, Copy, PartialEq, Debug, Default)]
128152
enum slot {
129153
#[default]

tests/unit/out/refcount/union_basic.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,19 @@ impl Default for basic {
3131
}
3232
}
3333
}
34-
impl ByteRepr for basic {}
34+
impl ByteRepr for basic {
35+
fn byte_size() -> usize {
36+
4
37+
}
38+
fn to_bytes(&self, buf: &mut [u8]) {
39+
buf.copy_from_slice(&self.__bytes.borrow());
40+
}
41+
fn from_bytes(buf: &[u8]) -> Self {
42+
basic {
43+
__bytes: Rc::new(RefCell::new(Box::from(buf))),
44+
}
45+
}
46+
}
3547
pub fn main() {
3648
std::process::exit(main_0());
3749
}

tests/unit/out/refcount/union_pointer_pun_writethrough.rs

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,19 @@ fn main_0() -> i32 {
3636
}
3737
}
3838
}
39-
impl ByteRepr for anon_0 {};
39+
impl ByteRepr for anon_0 {
40+
fn byte_size() -> usize {
41+
8
42+
}
43+
fn to_bytes(&self, buf: &mut [u8]) {
44+
buf.copy_from_slice(&self.__bytes.borrow());
45+
}
46+
fn from_bytes(buf: &[u8]) -> Self {
47+
anon_0 {
48+
__bytes: Rc::new(RefCell::new(Box::from(buf))),
49+
}
50+
}
51+
};
4052
let pp: Value<anon_0> = <Value<anon_0>>::default();
4153
(*pp.borrow_mut()).as_signed().write((x.as_pointer()));
4254
((*pp.borrow()).as_unsigned().read()).write(42_u64);

tests/unit/out/refcount/union_tagged_struct_arms.rs

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -122,14 +122,42 @@ impl Default for anon_0 {
122122
}
123123
}
124124
}
125-
impl ByteRepr for anon_0 {}
125+
impl ByteRepr for anon_0 {
126+
fn byte_size() -> usize {
127+
40
128+
}
129+
fn to_bytes(&self, buf: &mut [u8]) {
130+
buf.copy_from_slice(&self.__bytes.borrow());
131+
}
132+
fn from_bytes(buf: &[u8]) -> Self {
133+
anon_0 {
134+
__bytes: Rc::new(RefCell::new(Box::from(buf))),
135+
}
136+
}
137+
}
126138
#[derive(Default)]
127139
pub struct Branch {
128140
pub choice: Value<Choice_enum>,
129141
pub index: Value<i32>,
130142
pub v: Value<anon_0>,
131143
}
132-
impl ByteRepr for Branch {}
144+
impl ByteRepr for Branch {
145+
fn byte_size() -> usize {
146+
48
147+
}
148+
fn to_bytes(&self, buf: &mut [u8]) {
149+
(*self.choice.borrow()).to_bytes(&mut buf[0..4]);
150+
(*self.index.borrow()).to_bytes(&mut buf[4..8]);
151+
(*self.v.borrow()).to_bytes(&mut buf[8..48]);
152+
}
153+
fn from_bytes(buf: &[u8]) -> Self {
154+
Self {
155+
choice: Rc::new(RefCell::new(<Choice_enum>::from_bytes(&buf[0..4]))),
156+
index: Rc::new(RefCell::new(<i32>::from_bytes(&buf[4..8]))),
157+
v: Rc::new(RefCell::new(<anon_0>::from_bytes(&buf[8..48]))),
158+
}
159+
}
160+
}
133161
pub fn main() {
134162
std::process::exit(main_0());
135163
}

0 commit comments

Comments
 (0)