Skip to content

Commit 9da481b

Browse files
committed
Implement ByteRepr for structs with ByteRepr fields
1 parent d0c9003 commit 9da481b

1 file changed

Lines changed: 62 additions & 1 deletion

File tree

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

0 commit comments

Comments
 (0)