@@ -626,7 +626,11 @@ void ConverterRefCount::EmitRustUnion(clang::RecordDecl *decl) {
626626 ctx_, ctx_.getCanonicalTagType (decl),
627627 std::vector<std::string>(attrs.begin (), attrs.end ()));
628628
629- StrCat (std::format (" pub struct {} {{ __bytes: Value<Box<[u8]>> }}" , name));
629+ auto size = ctx_.getTypeSizeInChars (ctx_.getCanonicalTagType (decl));
630+ StrCat (std::format (" #[derive(ByteRepr)] #[byte_size({0})] pub struct {1} {{ "
631+ " #[offset(0)] #[byte_size({0})] __bytes: Value<Box<[u8]>> "
632+ " }}" ,
633+ size.getQuantity (), name));
630634
631635 StrCat (" impl" , name);
632636 {
@@ -647,84 +651,12 @@ void ConverterRefCount::EmitRustUnion(clang::RecordDecl *decl) {
647651
648652 AddCloneTrait (decl);
649653 AddDefaultTrait (decl);
650- AddByteReprTrait (decl);
651654}
652655
653- void ConverterRefCount::AddByteReprTrait (const clang::RecordDecl *decl) {
654- if (RecordDerivesByteRepr (decl)) {
655- return ;
656- }
657-
658- auto struct_name = GetRecordName (decl);
659-
660- if (!TypeImplementsByteRepr (ctx_.getCanonicalTagType (decl))) {
661- // The size locates the fields of the elements of arrays of structs.
662- StrCat (std::format (" impl ByteRepr for {}" , struct_name));
663- PushBrace brace (*this );
664- if (!decl->isUnion ()) {
665- StrCat (std::format (" fn byte_size() -> usize {{ {} }}" ,
666- ctx_.getTypeSize (ctx_.getCanonicalTagType (decl)) / 8 ));
667- }
668- return ;
669- }
670-
671- StrCat (" impl ByteRepr for " , struct_name);
672- PushBrace impl_brace (*this );
673-
674- if (decl->isUnion ()) {
675- StrCat (std::format (" fn byte_size() -> usize {{ {} }}" ,
676- ctx_.getTypeSize (ctx_.getCanonicalTagType (decl)) / 8 ));
677- StrCat (" fn to_bytes(&self, buf: &mut [u8]) { "
678- " buf.copy_from_slice(&self.__bytes.borrow()); }" );
679- StrCat (std::format (" fn from_bytes(buf: &[u8]) -> Self {{ {} {{ __bytes: "
680- " Rc::new(RefCell::new(Box::from(buf))) }} }}" ,
681- struct_name));
682- return ;
683- }
684-
685- const auto &layout = ctx_.getASTRecordLayout (decl);
686-
687- StrCat (std::format (" fn byte_size() -> usize {{ {} }}" ,
688- ctx_.getTypeSize (ctx_.getCanonicalTagType (decl)) / 8 ));
689-
690- StrCat (" fn to_bytes(&self, buf: &mut [u8])" );
691- {
692- PushBrace fn_brace (*this );
693- unsigned idx = 0 ;
694- for (auto *field : decl->fields ()) {
695- auto byte_off = layout.getFieldOffset (idx) / 8 ;
696- auto byte_size = ctx_.getTypeSize (field->getType ()) / 8 ;
697- auto value = " self." + GetNamedDeclAsString (field);
698- if (IsValueField (ctx_, field)) {
699- value = std::format (" (*{}.borrow())" , value);
700- }
701- StrCat (std::format (" {}.to_bytes(&mut buf[{}..{}]);" , value, byte_off,
702- byte_off + byte_size));
703- ++idx;
704- }
705- }
706-
707- StrCat (" fn from_bytes(buf: &[u8]) -> Self" );
708- {
709- PushBrace fn_brace (*this );
710- StrCat (" Self" );
711- PushBrace lit_brace (*this );
712- unsigned idx = 0 ;
713- for (auto *field : decl->fields ()) {
714- auto byte_off = layout.getFieldOffset (idx) / 8 ;
715- auto byte_size = ctx_.getTypeSize (field->getType ()) / 8 ;
716- PushConversionKind push (*this , ConversionKind::FullRefCount);
717- std::string storage_ty = ToString (field->getType ());
718- Unwrap (storage_ty, " Value<" , " >" );
719- auto value = std::format (" <{}>::from_bytes(&buf[{}..{}])" , storage_ty,
720- byte_off, byte_off + byte_size);
721- if (IsValueField (ctx_, field)) {
722- value = std::format (" Rc::new(RefCell::new({}))" , value);
723- }
724- StrCat (std::format (" {}: {}," , GetNamedDeclAsString (field), value));
725- ++idx;
726- }
727- }
656+ void ConverterRefCount::EmitByteSizeAttr (const clang::RecordDecl *decl) {
657+ StrCat (std::format (
658+ " #[byte_size({})]" ,
659+ ctx_.getTypeSizeInChars (ctx_.getCanonicalTagType (decl)).getQuantity ()));
728660}
729661
730662std::string
@@ -745,6 +677,14 @@ bool ConverterRefCount::VisitFieldDecl(clang::FieldDecl *decl) {
745677 const auto &layout = ctx_.getASTRecordLayout (decl->getParent ());
746678 StrCat (std::format (" #[offset({})]" ,
747679 layout.getFieldOffset (decl->getFieldIndex ()) / 8 ));
680+ // Only arithmetic types have the same size in Rust as in C.
681+ auto type = decl->getType ().getCanonicalType ();
682+ if (!type->isIntegerType () &&
683+ !type->isSpecificBuiltinType (clang::BuiltinType::Float) &&
684+ !type->isSpecificBuiltinType (clang::BuiltinType::Double)) {
685+ StrCat (std::format (" #[byte_size({})]" ,
686+ ctx_.getTypeSizeInChars (decl->getType ()).getQuantity ()));
687+ }
748688 PushConversionKind push (*this , IsValueField (ctx_, decl)
749689 ? ConversionKind::FullRefCount
750690 : ConversionKind::Pointee);
@@ -2356,10 +2296,8 @@ ConverterRefCount::GetStructAttributes(const clang::RecordDecl *decl) {
23562296
23572297 // Gives access to the fields through pointers to them.
23582298 attrs.emplace_back (" Record" );
2359-
2360- if (RecordDerivesByteRepr (decl)) {
2361- attrs.emplace_back (" ByteRepr" );
2362- }
2299+ // Gives access to the bytes of the struct, at the offsets of its fields.
2300+ attrs.emplace_back (" ByteRepr" );
23632301
23642302 if (RecordImplementsClone (decl)) {
23652303 attrs.emplace_back (" VaArg" );
0 commit comments