Skip to content

Add safe translation for unions#205

Merged
nunoplopes merged 14 commits into
Cpp2Rust:masterfrom
lucic71:union-storage
Jun 25, 2026
Merged

Add safe translation for unions#205
nunoplopes merged 14 commits into
Cpp2Rust:masterfrom
lucic71:union-storage

Conversation

@lucic71

@lucic71 lucic71 commented Jun 25, 2026

Copy link
Copy Markdown
Contributor

C/C++ unions are translated as a byte buffer + accessors that return a reinterpreted pointer into the byte buffer.

This C/C++ union:

union basic {
  int i;
  float f;
};

becomes:

pub struct basic {
    __bytes: Value<Box<[u8]>>,
}
impl basic {
    pub fn i(&self) -> Ptr<i32> {
        (self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
    }
    pub fn f(&self) -> Ptr<f32> {
        (self.__bytes.as_pointer() as Ptr<u8>).reinterpret_cast()
    }
}

Where __bytes is the byte buffer and i() and f() are the accessors that return reinterpreted views into the backing buffer.

Compared to Rust unsafe/C/C++ unions, this implementation is safe because it always serializes/deserializes the bytes into valid values or panics otherwise.

PushBrace impl_brace(*this);
StrCat("fn default() -> Self");
PushBrace fn_brace(*this);
StrCat(std::format("{} {{ __bytes: Rc::new(RefCell::new(vec![0u8; "

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think Box::from([0u8; {}]) is more efficient

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

They should be the same: https://godbolt.org/z/z59EYY6Wb. Historically Box::from([0u8; {}]) made a stack allocation for the array then copied the array on heap. But that seems to be solved so I will use your suggestion

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

auto record_name = GetRecordName(decl);

if (decl->isUnion()) {
StrCat(std::format("impl Clone for {}", record_name));

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a lot of these formats are wasteful. It's better to do StrCat("impl Clone for", record_name)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

@nunoplopes nunoplopes merged commit 8ab5569 into Cpp2Rust:master Jun 25, 2026
9 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants