From 5d6a5dec3098b065ccf612ef8841bbf7925a0a95 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 29 Jun 2026 16:25:45 +0100 Subject: [PATCH 1/2] Add ByteRepr for union --- cpp2rust/converter/converter_lib.cpp | 2 +- cpp2rust/converter/models/converter_refcount.cpp | 13 ++++++++++++- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index 6332cdba..2eafb1c1 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -213,7 +213,7 @@ bool TypeImplementsByteRepr(clang::QualType qt) { return false; } if (rd->isUnion()) { - return false; + return true; } for (const auto *field : rd->fields()) { if (!TypeImplementsByteRepr(field->getType())) { diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index fa484685..72f8f143 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -554,9 +554,20 @@ void ConverterRefCount::AddByteReprTrait(const clang::RecordDecl *decl) { return; } - StrCat(std::format("impl ByteRepr for {}", struct_name)); + StrCat("impl ByteRepr for ", struct_name); PushBrace impl_brace(*this); + if (decl->isUnion()) { + StrCat(std::format("fn byte_size() -> usize {{ {} }}", + ctx_.getTypeSize(ctx_.getCanonicalTagType(decl)) / 8)); + StrCat("fn to_bytes(&self, buf: &mut [u8]) { " + "buf.copy_from_slice(&self.__bytes.borrow()); }"); + StrCat(std::format("fn from_bytes(buf: &[u8]) -> Self {{ {} {{ __bytes: " + "Rc::new(RefCell::new(Box::from(buf))) }} }}", + struct_name)); + return; + } + const auto &layout = ctx_.getASTRecordLayout(decl); StrCat(std::format("fn byte_size() -> usize {{ {} }}", From d3c555f1d3cf1f6c5d6de5e24eead3f3e81dd837 Mon Sep 17 00:00:00 2001 From: Lucian Popescu Date: Mon, 29 Jun 2026 16:49:01 +0100 Subject: [PATCH 2/2] Update tests --- .../refcount/tag_vs_identifier_collision.rs | 28 ++++++++++++++-- tests/unit/out/refcount/union_basic.rs | 14 +++++++- .../union_pointer_pun_writethrough.rs | 14 +++++++- .../out/refcount/union_tagged_struct_arms.rs | 32 +++++++++++++++++-- 4 files changed, 82 insertions(+), 6 deletions(-) diff --git a/tests/unit/out/refcount/tag_vs_identifier_collision.rs b/tests/unit/out/refcount/tag_vs_identifier_collision.rs index bf14ce14..a3a2fb9d 100644 --- a/tests/unit/out/refcount/tag_vs_identifier_collision.rs +++ b/tests/unit/out/refcount/tag_vs_identifier_collision.rs @@ -97,7 +97,19 @@ impl Default for point { } } } -impl ByteRepr for point {} +impl ByteRepr for point { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + buf.copy_from_slice(&self.__bytes.borrow()); + } + fn from_bytes(buf: &[u8]) -> Self { + point { + __bytes: Rc::new(RefCell::new(Box::from(buf))), + } + } +} pub struct slot_union { __bytes: Value>, } @@ -123,7 +135,19 @@ impl Default for slot_union { } } } -impl ByteRepr for slot_union {} +impl ByteRepr for slot_union { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + buf.copy_from_slice(&self.__bytes.borrow()); + } + fn from_bytes(buf: &[u8]) -> Self { + slot_union { + __bytes: Rc::new(RefCell::new(Box::from(buf))), + } + } +} #[derive(Clone, Copy, PartialEq, Debug, Default)] enum slot { #[default] diff --git a/tests/unit/out/refcount/union_basic.rs b/tests/unit/out/refcount/union_basic.rs index 9988b7b7..0a509632 100644 --- a/tests/unit/out/refcount/union_basic.rs +++ b/tests/unit/out/refcount/union_basic.rs @@ -31,7 +31,19 @@ impl Default for basic { } } } -impl ByteRepr for basic {} +impl ByteRepr for basic { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + buf.copy_from_slice(&self.__bytes.borrow()); + } + fn from_bytes(buf: &[u8]) -> Self { + basic { + __bytes: Rc::new(RefCell::new(Box::from(buf))), + } + } +} pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/union_pointer_pun_writethrough.rs b/tests/unit/out/refcount/union_pointer_pun_writethrough.rs index 12c36840..dd2f9369 100644 --- a/tests/unit/out/refcount/union_pointer_pun_writethrough.rs +++ b/tests/unit/out/refcount/union_pointer_pun_writethrough.rs @@ -36,7 +36,19 @@ fn main_0() -> i32 { } } } - impl ByteRepr for anon_0 {}; + impl ByteRepr for anon_0 { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + buf.copy_from_slice(&self.__bytes.borrow()); + } + fn from_bytes(buf: &[u8]) -> Self { + anon_0 { + __bytes: Rc::new(RefCell::new(Box::from(buf))), + } + } + }; let pp: Value = >::default(); (*pp.borrow_mut()).as_signed().write((x.as_pointer())); ((*pp.borrow()).as_unsigned().read()).write(42_u64); diff --git a/tests/unit/out/refcount/union_tagged_struct_arms.rs b/tests/unit/out/refcount/union_tagged_struct_arms.rs index 4155c690..3e657850 100644 --- a/tests/unit/out/refcount/union_tagged_struct_arms.rs +++ b/tests/unit/out/refcount/union_tagged_struct_arms.rs @@ -122,14 +122,42 @@ impl Default for anon_0 { } } } -impl ByteRepr for anon_0 {} +impl ByteRepr for anon_0 { + fn byte_size() -> usize { + 40 + } + fn to_bytes(&self, buf: &mut [u8]) { + buf.copy_from_slice(&self.__bytes.borrow()); + } + fn from_bytes(buf: &[u8]) -> Self { + anon_0 { + __bytes: Rc::new(RefCell::new(Box::from(buf))), + } + } +} #[derive(Default)] pub struct Branch { pub choice: Value, pub index: Value, pub v: Value, } -impl ByteRepr for Branch {} +impl ByteRepr for Branch { + fn byte_size() -> usize { + 48 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.choice.borrow()).to_bytes(&mut buf[0..4]); + (*self.index.borrow()).to_bytes(&mut buf[4..8]); + (*self.v.borrow()).to_bytes(&mut buf[8..48]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + choice: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + index: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + v: Rc::new(RefCell::new(::from_bytes(&buf[8..48]))), + } + } +} pub fn main() { std::process::exit(main_0()); }