diff --git a/cpp2rust/converter/converter.cpp b/cpp2rust/converter/converter.cpp index 9ba109d2..81cbc1ca 100644 --- a/cpp2rust/converter/converter.cpp +++ b/cpp2rust/converter/converter.cpp @@ -55,12 +55,15 @@ use std::rc::Rc; )"); } -std::string Converter::EmitOpaqueRecords() { +std::string Converter::EmitOpaqueRecords(bool emit_byte_repr) { std::string out; record_decls_.ForEachUndefined([&](const std::string &name) { out += "pub struct "; out += name; out += ";\n"; + if (emit_byte_repr) { + out += "impl ByteRepr for " + name + " {}\n"; + } }); return out; } @@ -753,6 +756,11 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) { } } + if (decl->isUnion()) { + EmitRustUnion(decl); + return; + } + // Derived traits if (EmitsReprCForRecords()) { StrCat("#[repr(C)]"); @@ -770,8 +778,7 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) { auto access = clang::dyn_cast(decl) ? AccessSpecifierAsString(decl->getAccess()) : keyword::kPub; - StrCat(access, decl->isUnion() ? keyword::kUnion : keyword::kStruct, - GetRecordName(decl)); + StrCat(access, keyword::kStruct, GetRecordName(decl)); { PushBrace brace(*this); for (auto *field : decl->fields()) { @@ -817,6 +824,31 @@ void Converter::EmitRustStructOrUnion(clang::RecordDecl *decl) { AddByteReprTrait(decl); } +void Converter::EmitRustUnion(clang::RecordDecl *decl) { + if (EmitsReprCForRecords()) { + StrCat("#[repr(C)]"); + } + auto attrs = GetStructAttributes(decl); + Mapper::SetDerives(ctx_.getCanonicalTagType(decl), + std::vector(attrs.begin(), attrs.end())); + StrCat("#[derive("); + for (auto *attr : attrs) { + StrCat(attr, ','); + } + StrCat(")]"); + + StrCat(keyword::kPub, keyword::kUnion, GetRecordName(decl)); + { + PushBrace brace(*this); + for (auto *field : decl->fields()) { + VisitFieldDecl(field); + } + } + + AddDefaultTrait(decl); + AddByteReprTrait(decl); +} + bool Converter::VisitCXXRecordDecl(clang::CXXRecordDecl *decl) { if (clang::isa(decl)) { materializeTemplateSpecialization(decl); @@ -3136,6 +3168,7 @@ bool Converter::VisitEnumDecl(clang::EnumDecl *decl) { AddFromImpl(decl); AddIncDecImpls(decl); + AddByteReprTrait(decl); return false; } @@ -3918,6 +3951,8 @@ void Converter::EmitDefaultStructLiteral(const clang::RecordDecl *decl) { void Converter::AddByteReprTrait(const clang::RecordDecl *decl) {} +void Converter::AddByteReprTrait(const clang::EnumDecl *decl) {} + void Converter::ConvertUnsignedArithBinaryOperator(clang::BinaryOperator *op, clang::Expr *expr) { StrCat(token::kDot); diff --git a/cpp2rust/converter/converter.h b/cpp2rust/converter/converter.h index 63de20e4..7d0f2571 100644 --- a/cpp2rust/converter/converter.h +++ b/cpp2rust/converter/converter.h @@ -50,7 +50,7 @@ class Converter : public clang::RecursiveASTVisitor { virtual void EmitFilePreamble(); - static std::string EmitOpaqueRecords(); + static std::string EmitOpaqueRecords(bool emit_byte_repr); virtual bool VisitBuiltinType(clang::BuiltinType *type); @@ -112,6 +112,8 @@ class Converter : public clang::RecursiveASTVisitor { virtual void EmitRustStructOrUnion(clang::RecordDecl *decl); + virtual void EmitRustUnion(clang::RecordDecl *decl); + virtual bool EmitsReprCForRecords() const { return true; } virtual bool VisitCXXMethodDecl(clang::CXXMethodDecl *decl); @@ -539,6 +541,8 @@ class Converter : public clang::RecursiveASTVisitor { virtual void AddByteReprTrait(const clang::RecordDecl *decl); + virtual void AddByteReprTrait(const clang::EnumDecl *decl); + virtual void ConvertUnsignedArithBinaryOperator(clang::BinaryOperator *binary_operator, clang::Expr *expr); diff --git a/cpp2rust/converter/converter_lib.cpp b/cpp2rust/converter/converter_lib.cpp index 12c0bf69..60fa9c65 100644 --- a/cpp2rust/converter/converter_lib.cpp +++ b/cpp2rust/converter/converter_lib.cpp @@ -199,6 +199,42 @@ bool IsMut(clang::QualType qual_type) { qual_type->getPointeeType().isConstQualified()); } +bool TypeImplementsByteRepr(clang::QualType qt) { + if (qt->isIntegerType() || qt->isFloatingType()) { + return true; + } + if (qt->isPointerType()) { + return true; + } + if (const auto *arr = qt->getAsArrayTypeUnsafe()) { + return TypeImplementsByteRepr(arr->getElementType()); + } + if (const auto *rd = qt->getAsRecordDecl()) { + if (rd->isUnion()) { + return true; + } + for (const auto *field : rd->fields()) { + if (!TypeImplementsByteRepr(field->getType())) { + return false; + } + } + return true; + } + return false; +} + +bool RustSizeDivergesFromC(clang::QualType qt) { + qt = qt.getCanonicalType(); + // Records have Rc> fields that diverge from the C size + if (qt->isRecordType()) { + return true; + } + if (auto *arr = qt->getAsArrayTypeUnsafe()) { + return RustSizeDivergesFromC(arr->getElementType()); + } + return false; +} + bool IsMutatingCall(const clang::CallExpr *expr) { if (auto *callee = expr->getDirectCallee()) { if (auto *method = clang::dyn_cast(callee)) { diff --git a/cpp2rust/converter/converter_lib.h b/cpp2rust/converter/converter_lib.h index a09e0e5d..cd7e9d5a 100644 --- a/cpp2rust/converter/converter_lib.h +++ b/cpp2rust/converter/converter_lib.h @@ -51,6 +51,10 @@ bool IsUnsignedArithOp(const clang::BinaryOperator *expr); bool IsMut(clang::QualType qual_type); +bool TypeImplementsByteRepr(clang::QualType qt); + +bool RustSizeDivergesFromC(clang::QualType qt); + bool IsMutatingCall(const clang::CallExpr *expr); bool IsOverloadedFunction(const clang::FunctionDecl *decl); diff --git a/cpp2rust/converter/models/converter_refcount.cpp b/cpp2rust/converter/models/converter_refcount.cpp index 7fb3bc9a..ff3dec67 100644 --- a/cpp2rust/converter/models/converter_refcount.cpp +++ b/cpp2rust/converter/models/converter_refcount.cpp @@ -469,6 +469,46 @@ void ConverterRefCount::AddDefaultTrait(const clang::RecordDecl *decl) { } void ConverterRefCount::AddDefaultTraitForUnion(const clang::RecordDecl *decl) { + auto name = GetRecordName(decl); + StrCat(std::format("impl Default for {}", name)); + PushBrace impl_brace(*this); + StrCat("fn default() -> Self"); + PushBrace fn_brace(*this); + StrCat(std::format("{} {{ __store: libcc2rs::UnionStorage::new({}) }}", name, + ctx_.getASTRecordLayout(decl).getSize().getQuantity())); +} + +void ConverterRefCount::EmitRustUnion(clang::RecordDecl *decl) { + auto name = GetRecordName(decl); + + auto attrs = GetStructAttributes(decl); + Mapper::SetDerives(ctx_.getCanonicalTagType(decl), + std::vector(attrs.begin(), attrs.end())); + StrCat("#[derive("); + for (auto *attr : attrs) { + StrCat(attr, ','); + } + StrCat(")]"); + + StrCat(std::format("pub struct {} {{ __store: libcc2rs::UnionStorage, }}", + name)); + + StrCat(std::format("impl {}", name)); + { + PushBrace impl_brace(*this); + for (auto *field : decl->fields()) { + PushConversionKind push(*this, ConversionKind::FullRefCount); + std::string storage_ty = ToString(field->getType()); + Unwrap(storage_ty, "Value<", ">"); + auto byte_size = ctx_.getTypeSize(field->getType()) / 8; + StrCat(std::format("pub fn {}(&self) -> Ptr<{}> {{ " + "self.__store.reinterpret_sized(0, {}) }}", + GetNamedDeclAsString(field), storage_ty, byte_size)); + } + } + + AddDefaultTrait(decl); + AddByteReprTrait(decl); } void ConverterRefCount::AddDropTrait(const clang::CXXRecordDecl *decl) { @@ -501,30 +541,23 @@ void ConverterRefCount::AddDropTrait(const clang::CXXRecordDecl *decl) { StrCat('}'); } -static bool recordImplementsByteRepr(const clang::RecordDecl *decl) { - if (decl->isUnion()) { - return false; - } - - // ByteRepr is only supported for user-defined structs that contain ByteRepr - // fields. - for (auto *f : decl->fields()) { - auto qt = f->getType(); - if (qt->isEnumeralType()) { - return false; - } - if (!qt->isIntegerType() && !qt->isFloatingType()) { - return false; - } - } - - return true; -} - void ConverterRefCount::AddByteReprTrait(const clang::RecordDecl *decl) { auto struct_name = GetRecordName(decl); - if (!recordImplementsByteRepr(decl)) { + if (decl->isUnion()) { + StrCat(std::format("impl ByteRepr for {}", struct_name)); + PushBrace impl_brace(*this); + StrCat(std::format("fn byte_size() -> usize {{ {} }}", + ctx_.getTypeSize(ctx_.getCanonicalTagType(decl)) / 8)); + StrCat( + "fn to_bytes(&self, buf: &mut [u8]) { self.__store.to_bytes(buf); }"); + StrCat(std::format("fn from_bytes(buf: &[u8]) -> Self {{ {} {{ __store: " + "libcc2rs::UnionStorage::from_bytes(buf) }} }}", + struct_name)); + return; + } + + if (!TypeImplementsByteRepr(ctx_.getCanonicalTagType(decl))) { StrCat(std::format("impl ByteRepr for {}", struct_name)); PushBrace brace(*this); return; @@ -535,6 +568,9 @@ void ConverterRefCount::AddByteReprTrait(const clang::RecordDecl *decl) { const auto &layout = ctx_.getASTRecordLayout(decl); + StrCat(std::format("fn byte_size() -> usize {{ {} }}", + ctx_.getTypeSize(ctx_.getCanonicalTagType(decl)) / 8)); + StrCat("fn to_bytes(&self, buf: &mut [u8])"); { PushBrace fn_brace(*this); @@ -558,15 +594,31 @@ void ConverterRefCount::AddByteReprTrait(const clang::RecordDecl *decl) { for (auto *field : decl->fields()) { auto byte_off = layout.getFieldOffset(idx) / 8; auto byte_size = ctx_.getTypeSize(field->getType()) / 8; + PushConversionKind push(*this, ConversionKind::FullRefCount); + std::string storage_ty = ToString(field->getType()); + Unwrap(storage_ty, "Value<", ">"); StrCat(std::format( "{}: Rc::new(RefCell::new(<{}>::from_bytes(&buf[{}..{}]))),", - GetNamedDeclAsString(field), Mapper::Map(field->getType()), byte_off, + GetNamedDeclAsString(field), storage_ty, byte_off, byte_off + byte_size)); ++idx; } } } +void ConverterRefCount::AddByteReprTrait(const clang::EnumDecl *decl) { + auto name = GetRecordName(decl); + StrCat(std::format("impl ByteRepr for {}", name)); + PushBrace impl_brace(*this); + StrCat(std::format("fn byte_size() -> usize {{ {} }}", + ctx_.getTypeSize(ctx_.getCanonicalTagType(decl)) / 8)); + StrCat( + "fn to_bytes(&self, buf: &mut [u8]) { (*self as i32).to_bytes(buf); }"); + StrCat(std::format("fn from_bytes(buf: &[u8]) -> Self {{ " + "<{}>::from(i32::from_bytes(buf)) }}", + name)); +} + std::string ConverterRefCount::GetSelfMaybeWithMut(const clang::CXXMethodDecl *decl) { return "&self"; @@ -1246,7 +1298,7 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) { expr->getType()->isPointerType()) { Convert(expr->getSubExpr()); PushConversionKind push(*this, ConversionKind::Unboxed); - StrCat(std::format(".cast::<{}>().expect(\"ub:wrong type\")", + StrCat(std::format(".reinterpret_cast::<{}>()", ConvertPointeeType(expr->getType()))); return false; } else if (expr->getType()->isVoidPointerType() && @@ -1258,9 +1310,17 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) { } else if (expr->getSubExpr()->getType()->isPointerType() && !expr->getSubExpr()->isNullPointerConstant( ctx_, clang::Expr::NPC_ValueDependentIsNull)) { - StrCat(std::format("({}.to_strong().as_pointer() as {})", - ToString(expr->getSubExpr()), - ToString(expr->getType()))); + auto src_pointee = expr->getSubExpr()->getType()->getPointeeType(); + auto dst_pointee = expr->getType()->getPointeeType(); + if (ctx_.hasSameUnqualifiedType(src_pointee, dst_pointee)) { + StrCat(std::format("({}.to_strong().as_pointer() as {})", + ToString(expr->getSubExpr()), + ToString(expr->getType()))); + } else { + StrCat(std::format("{}.reinterpret_cast::<{}>()", + ToString(expr->getSubExpr()), + ConvertPointeeType(expr->getType()))); + } return false; } return Converter::VisitExplicitCastExpr(expr); @@ -1269,6 +1329,20 @@ bool ConverterRefCount::VisitExplicitCastExpr(clang::ExplicitCastExpr *expr) { } } +bool ConverterRefCount::VisitUnaryExprOrTypeTraitExpr( + clang::UnaryExprOrTypeTraitExpr *expr) { + if (expr->getKind() == clang::UnaryExprOrTypeTrait::UETT_SizeOf) { + auto arg_type = expr->isArgumentType() ? expr->getArgumentType() + : expr->getArgumentExpr()->getType(); + if (RustSizeDivergesFromC(arg_type)) { + StrCat(std::format("{}usize", ctx_.getTypeSize(arg_type) / 8)); + computed_expr_type_ = ComputedExprType::FreshValue; + return false; + } + } + return Converter::VisitUnaryExprOrTypeTraitExpr(expr); +} + bool ConverterRefCount::VisitStmtExpr(clang::StmtExpr *expr) { PushConversionKind push(*this, ConversionKind::FullRefCount); return Converter::VisitStmtExpr(expr); @@ -1451,6 +1525,43 @@ bool ConverterRefCount::VisitMemberExpr(clang::MemberExpr *expr) { return false; } + if (auto *parent = + clang::dyn_cast(member->getDeclContext()); + parent && parent->isUnion() && clang::isa(member)) { + std::string str; + { + Buffer buf(*this); + PushExprKind push(*this, + isLValue() ? ExprKind::LValue : ExprKind::RValue); + Converter::ConvertMemberExpr(expr); + str = std::move(buf).str(); + } + str += "()"; + + if (isAddrOf()) { + if (member->getType()->isArrayType()) { + PushConversionKind push(*this, ConversionKind::Unboxed); + StrCat(std::format( + "{}.reinterpret_cast::<{}>()", str, + ToString( + member->getType()->getAsArrayTypeUnsafe()->getElementType()))); + } else { + StrCat(str); + } + computed_expr_type_ = ComputedExprType::FreshPointer; + return false; + } + if (isLValue()) { + pending_deref_.set(str); + if (member->getType()->isRecordType()) { + StrCat("__v"); + } + return false; + } + StrCat(DerefPtrExpr(str, member->getType())); + return false; + } + std::string str; if (known) { str = GetMappedAsString(expr); @@ -1789,6 +1900,11 @@ std::vector ConverterRefCount::GetStructAttributes(const clang::RecordDecl *decl) { std::vector attrs; + if (decl->isUnion()) { + attrs.emplace_back("Clone"); + return attrs; + } + if (RecordDerivesDefault(decl)) { attrs.emplace_back("Default"); } @@ -1876,7 +1992,11 @@ void ConverterRefCount::EmitSetOrAssign(clang::Expr *lhs, auto lhs_str = ConvertLValue(lhs); if (!pending_deref_.empty()) { auto ptr = pending_deref_.take(); - StrCat(ptr, ".write(", rhs, ')'); + if (lhs_str.empty()) { + StrCat(ptr, ".write(", rhs, ')'); + } else { + StrCat(ptr, ".with_mut(|__v| ", lhs_str, token::kAssign, rhs, ')'); + } } else { StrCat(lhs_str, token::kAssign, rhs); } diff --git a/cpp2rust/converter/models/converter_refcount.h b/cpp2rust/converter/models/converter_refcount.h index 0d9d9296..cf2a1bcb 100644 --- a/cpp2rust/converter/models/converter_refcount.h +++ b/cpp2rust/converter/models/converter_refcount.h @@ -28,6 +28,8 @@ class ConverterRefCount final : public Converter { bool VisitCXXRecordDecl(clang::CXXRecordDecl *decl) override; + void EmitRustUnion(clang::RecordDecl *decl) override; + bool EmitsReprCForRecords() const override { return false; } void ConvertOrdAndPartialOrdTraits(const clang::CXXRecordDecl *decl, @@ -39,6 +41,11 @@ class ConverterRefCount final : public Converter { void AddByteReprTrait(const clang::RecordDecl *decl) override; + void AddByteReprTrait(const clang::EnumDecl *decl) override; + + bool + VisitUnaryExprOrTypeTraitExpr(clang::UnaryExprOrTypeTraitExpr *expr) override; + void AddDefaultTrait(const clang::RecordDecl *decl) override; void AddDefaultTraitForUnion(const clang::RecordDecl *decl) override; diff --git a/cpp2rust/cpp2rust_lib.cpp b/cpp2rust/cpp2rust_lib.cpp index 100d6d93..a19a03c3 100644 --- a/cpp2rust/cpp2rust_lib.cpp +++ b/cpp2rust/cpp2rust_lib.cpp @@ -30,7 +30,7 @@ std::string TranspileSrc(std::string_view cc_code, Model model, rules_dir), cc_code, tool_args, std::filesystem::path(filename).filename().string(), filename.ends_with(".c") ? CLANG_C_COMPILER : CLANG_CXX_COMPILER); - rs_code += Converter::EmitOpaqueRecords(); + rs_code += Converter::EmitOpaqueRecords(model == Model::kRefCount); return rs_code; } @@ -70,7 +70,7 @@ std::string TranspileDir(std::string_view build_dir, Model model, std::string rs_code; FrontendActionFactory factory(rs_code, model, rules_dir); Tool.run(&factory); - rs_code += Converter::EmitOpaqueRecords(); + rs_code += Converter::EmitOpaqueRecords(model == Model::kRefCount); return rs_code; } } // namespace cpp2rust diff --git a/libcc2rs/src/fn_ptr.rs b/libcc2rs/src/fn_ptr.rs index 2ccc150e..81b5e6b5 100644 --- a/libcc2rs/src/fn_ptr.rs +++ b/libcc2rs/src/fn_ptr.rs @@ -6,7 +6,7 @@ use std::marker::PhantomData; use std::ops::Deref; use std::rc::Rc; -use crate::rc::{AnyPtr, ErasedPtr}; +use crate::rc::{AnyPtr, ErasedPtr, Ptr}; use crate::reinterpret::ByteRepr; pub trait FnAddr { @@ -146,24 +146,21 @@ impl Eq for FnPtr {} impl ByteRepr for FnPtr {} impl ErasedPtr for FnPtr { - fn pointee_type_id(&self) -> TypeId { - TypeId::of::() - } - fn memcpy(&self, _src: &dyn ErasedPtr, _len: usize) { - panic!("memcpy not supported on fn pointer"); + fn as_bytes(&self) -> Ptr { + panic!("byte view not supported on fn pointer"); } fn as_any(&self) -> &dyn Any { self } - fn equals(&self, other: &dyn ErasedPtr) -> Option { - if self.pointee_type_id() != other.pointee_type_id() { - return None; - } - other.as_any().downcast_ref::>().map(|o| self == o) + fn equals(&self, other: &dyn ErasedPtr) -> bool { + other.as_any().downcast_ref::>() == Some(self) } fn is_null(&self) -> bool { FnPtr::is_null(self) } + fn address(&self) -> usize { + self.original.as_ref().map_or(0, |f| f.addr()) + } } impl FnPtr { diff --git a/libcc2rs/src/lib.rs b/libcc2rs/src/lib.rs index 4288464f..88c73e74 100644 --- a/libcc2rs/src/lib.rs +++ b/libcc2rs/src/lib.rs @@ -7,6 +7,9 @@ pub use reinterpret::ByteRepr; mod rc; pub use rc::*; +mod union; +pub use union::*; + mod fn_ptr; pub use fn_ptr::FnPtr; diff --git a/libcc2rs/src/rc.rs b/libcc2rs/src/rc.rs index ccf2f991..2af0866b 100644 --- a/libcc2rs/src/rc.rs +++ b/libcc2rs/src/rc.rs @@ -16,6 +16,13 @@ use crate::reinterpret::{ByteRepr, OriginalAlloc, SingleOriginalAlloc, SliceOrig pub type Value = Rc>; +struct ReinterpretedView { + // Pointer to the source of reinterpret + alloc: Rc, + // C++ byte size of one viewed value + byte_size: usize, +} + #[derive(Default)] enum PtrKind { #[default] @@ -25,7 +32,7 @@ enum PtrKind { HeapSingle(Weak>), HeapArray(Weak>>), Vec(Weak>>), - Reinterpreted(Rc), + Reinterpreted(Rc), } pub enum StrongPtr { @@ -41,6 +48,7 @@ pub enum StrongPtr { Reinterpreted { alloc: Rc, byte_offset: usize, + byte_size: usize, // Local buffer for deref(). None until first access. // Read-through: refreshed from alloc on every deref() call. cell: RefCell>, @@ -56,10 +64,11 @@ impl StrongPtr { StrongPtr::Reinterpreted { alloc, byte_offset, + byte_size, cell, } => { // Read-through: always re-read from the original allocation. - let mut buf = vec![0u8; std::mem::size_of::()]; + let mut buf = vec![0u8; *byte_size]; alloc.read_bytes(*byte_offset, &mut buf); *cell.borrow_mut() = Some(T::from_bytes(&buf)); Ref::map(cell.borrow(), |opt| opt.as_ref().unwrap()) @@ -77,8 +86,8 @@ impl fmt::Debug for PtrKind { PtrKind::HeapSingle(w) => write!(f, "HeapSingle({:?})", w.as_ptr()), PtrKind::StackArray(w) => write!(f, "StackArray({:?})", w.as_ptr()), PtrKind::HeapArray(w) => write!(f, "HeapArray({:?})", w.as_ptr()), - PtrKind::Reinterpreted(data) => { - write!(f, "Reinterpreted(0x{:x})", data.address()) + PtrKind::Reinterpreted(view) => { + write!(f, "Reinterpreted(0x{:x})", view.alloc.address()) } } } @@ -93,7 +102,7 @@ impl Clone for PtrKind { PtrKind::HeapSingle(weak) => PtrKind::HeapSingle(weak.clone()), PtrKind::StackArray(weak) => PtrKind::StackArray(weak.clone()), PtrKind::HeapArray(weak) => PtrKind::HeapArray(weak.clone()), - PtrKind::Reinterpreted(data) => PtrKind::Reinterpreted(Rc::clone(data)), + PtrKind::Reinterpreted(view) => PtrKind::Reinterpreted(Rc::clone(view)), } } } @@ -105,7 +114,7 @@ impl PtrKind { PtrKind::StackSingle(w) | PtrKind::HeapSingle(w) => w.as_ptr() as usize, PtrKind::Vec(w) => w.as_ptr() as usize, PtrKind::StackArray(w) | PtrKind::HeapArray(w) => w.as_ptr() as usize, - PtrKind::Reinterpreted(data) => data.address(), + PtrKind::Reinterpreted(view) => view.alloc.address(), } } } @@ -251,40 +260,40 @@ impl Ptr { #[inline] fn elem_step(&self) -> usize { match &self.kind { - PtrKind::Reinterpreted(_) => std::mem::size_of::(), + PtrKind::Reinterpreted(view) => view.byte_size, _ => 1, } } #[inline] pub fn len(&self) -> usize { - match self.kind { + match &self.kind { PtrKind::Null => 0, PtrKind::StackSingle(_) | PtrKind::HeapSingle(_) => 1, - PtrKind::Vec(ref weak) => weak.upgrade().expect("ub: dangling pointer").borrow().len(), - PtrKind::StackArray(ref weak) | PtrKind::HeapArray(ref weak) => { + PtrKind::Vec(weak) => weak.upgrade().expect("ub: dangling pointer").borrow().len(), + PtrKind::StackArray(weak) | PtrKind::HeapArray(weak) => { weak.upgrade().expect("ub: dangling pointer").borrow().len() } - PtrKind::Reinterpreted(ref data) => data.total_byte_len() / std::mem::size_of::(), + PtrKind::Reinterpreted(view) => view.alloc.total_byte_len() / view.byte_size, } } #[inline] pub fn is_empty(&self) -> bool { - match self.kind { + match &self.kind { PtrKind::Null => true, PtrKind::StackSingle(_) | PtrKind::HeapSingle(_) => false, - PtrKind::Vec(ref weak) => weak + PtrKind::Vec(weak) => weak .upgrade() .expect("ub: dangling pointer") .borrow() .is_empty(), - PtrKind::StackArray(ref weak) | PtrKind::HeapArray(ref weak) => weak + PtrKind::StackArray(weak) | PtrKind::HeapArray(weak) => weak .upgrade() .expect("ub: dangling pointer") .borrow() .is_empty(), - PtrKind::Reinterpreted(ref data) => self.offset >= data.total_byte_len(), + PtrKind::Reinterpreted(view) => self.offset >= view.alloc.total_byte_len(), } } @@ -339,9 +348,10 @@ impl Ptr { rc: weak.upgrade().expect("ub: dangling pointer"), offset: self.offset, }, - PtrKind::Reinterpreted(data) => StrongPtr::Reinterpreted { - alloc: Rc::clone(data), + PtrKind::Reinterpreted(view) => StrongPtr::Reinterpreted { + alloc: Rc::clone(&view.alloc), byte_offset: self.offset, + byte_size: view.byte_size, cell: RefCell::new(None), }, } @@ -365,10 +375,10 @@ impl Ptr { let rc = weak.upgrade().expect("ub: dangling pointer"); rc.borrow_mut()[self.offset] = value; } - PtrKind::Reinterpreted(data) => { - let mut buf = vec![0u8; std::mem::size_of::()]; + PtrKind::Reinterpreted(view) => { + let mut buf = vec![0u8; view.byte_size]; value.to_bytes(&mut buf); - data.write_bytes(self.offset, &buf); + view.alloc.write_bytes(self.offset, &buf); } } } @@ -391,7 +401,7 @@ impl Ptr { return self_any.downcast_ref::>().unwrap().clone(); } - if std::mem::size_of::() == 0 { + if U::byte_size() == 0 { panic!("cannot reinterpret_cast to zero-sized type"); } @@ -399,22 +409,25 @@ impl Ptr { PtrKind::Null => return Ptr::null(), PtrKind::StackSingle(weak) | PtrKind::HeapSingle(weak) => ( Rc::new(SingleOriginalAlloc { weak: weak.clone() }), - self.byte_offset(), + self.offset.wrapping_mul(T::byte_size()), ), PtrKind::Vec(weak) => ( Rc::new(SliceOriginalAlloc { weak: weak.clone() }), - self.byte_offset(), + self.offset.wrapping_mul(T::byte_size()), ), PtrKind::StackArray(weak) | PtrKind::HeapArray(weak) => ( Rc::new(SliceOriginalAlloc { weak: weak.clone() }), - self.byte_offset(), + self.offset.wrapping_mul(T::byte_size()), ), - PtrKind::Reinterpreted(data) => (Rc::clone(data), self.offset), + PtrKind::Reinterpreted(view) => (Rc::clone(&view.alloc), self.offset), }; Ptr { offset: abs_byte_off, - kind: PtrKind::Reinterpreted(alloc), + kind: PtrKind::Reinterpreted(Rc::new(ReinterpretedView { + alloc, + byte_size: U::byte_size(), + })), } } } @@ -441,13 +454,13 @@ impl Ptr { let mut borrow = rc.borrow_mut(); f(&mut borrow[self.offset]) } - PtrKind::Reinterpreted(data) => { - let mut buf = vec![0u8; std::mem::size_of::()]; - data.read_bytes(self.offset, &mut buf); + PtrKind::Reinterpreted(view) => { + let mut buf = vec![0u8; view.byte_size]; + view.alloc.read_bytes(self.offset, &mut buf); let mut val = T::from_bytes(&buf); let ret = f(&mut val); val.to_bytes(&mut buf); - data.write_bytes(self.offset, &buf); + view.alloc.write_bytes(self.offset, &buf); ret } } @@ -474,9 +487,9 @@ impl Ptr { let borrow = rc.borrow(); f(&borrow[self.offset]) } - PtrKind::Reinterpreted(data) => { - let mut buf = vec![0u8; std::mem::size_of::()]; - data.read_bytes(self.offset, &mut buf); + PtrKind::Reinterpreted(view) => { + let mut buf = vec![0u8; view.byte_size]; + view.alloc.read_bytes(self.offset, &mut buf); let val = T::from_bytes(&buf); f(&val) } @@ -501,9 +514,9 @@ impl Ptr { PtrKind::StackArray(ref weak) | PtrKind::HeapArray(ref weak) => { weak.upgrade().expect("ub: dangling pointer").borrow()[self.offset].clone() } - PtrKind::Reinterpreted(ref data) => { - let mut buf = vec![0u8; std::mem::size_of::()]; - data.read_bytes(self.offset, &mut buf); + PtrKind::Reinterpreted(ref view) => { + let mut buf = vec![0u8; view.byte_size]; + view.alloc.read_bytes(self.offset, &mut buf); T::from_bytes(&buf) } } @@ -535,7 +548,7 @@ impl Ptr { let strong = weak.upgrade().expect("ub: dangling pointer"); (*strong.borrow_mut())[self.get_offset()..last].sort(); } - PtrKind::Reinterpreted(..) => { + PtrKind::Reinterpreted(_) => { panic!("sorting not supported for reinterpreted pointers") } } @@ -580,7 +593,7 @@ impl Ptr { let mut borrow = strong.borrow_mut(); sort(&mut borrow, self.get_offset(), last, &mut cmp); } - PtrKind::Reinterpreted(..) => { + PtrKind::Reinterpreted(_) => { panic!("sorting not supported for reinterpreted pointers") } } @@ -856,7 +869,7 @@ impl ToOwnedOption for Ptr { } PtrKind::Vec(_) => panic!("Can't own a vector"), PtrKind::HeapArray(_) => panic!("Can't own an array variable as single"), - PtrKind::Reinterpreted(..) => panic!("Can't own a reinterpreted pointer"), + PtrKind::Reinterpreted(_) => panic!("Can't own a reinterpreted pointer"), } } } @@ -882,7 +895,7 @@ impl ToOwnedOption> for Ptr { } PtrKind::Vec(_) => panic!("Can't own a vector"), PtrKind::HeapSingle(_) => panic!("Can't own a single variable as an array"), - PtrKind::Reinterpreted(..) => panic!("Can't own a reinterpreted pointer"), + PtrKind::Reinterpreted(_) => panic!("Can't own a reinterpreted pointer"), } } } @@ -898,7 +911,7 @@ impl fmt::Debug for Ptr { (Weak::as_ptr(w) as usize).wrapping_add(self.byte_offset()) } PtrKind::Vec(w) => (Weak::as_ptr(w) as usize).wrapping_add(self.byte_offset()), - PtrKind::Reinterpreted(data) => data.address().wrapping_add(self.byte_offset()), + PtrKind::Reinterpreted(view) => view.alloc.address().wrapping_add(self.byte_offset()), }; write!(f, "0x{:x}", addr) } @@ -994,9 +1007,9 @@ impl Ptr { let raw = strong.borrow(); raw[start..end].to_vec() } - PtrKind::Reinterpreted(ref data) => { + PtrKind::Reinterpreted(ref view) => { let mut buf = vec![0u8; end.wrapping_sub(start)]; - data.read_bytes(start, &mut buf); + view.alloc.read_bytes(start, &mut buf); buf } } @@ -1031,11 +1044,17 @@ impl Ptr { } pub(crate) trait ErasedPtr: std::any::Any { - fn pointee_type_id(&self) -> std::any::TypeId; - fn memcpy(&self, src: &dyn ErasedPtr, len: usize); + fn as_bytes(&self) -> Ptr; fn as_any(&self) -> &dyn std::any::Any; - fn equals(&self, other: &dyn ErasedPtr) -> Option; + fn equals(&self, other: &dyn ErasedPtr) -> bool; fn is_null(&self) -> bool; + fn address(&self) -> usize; +} + +impl PartialEq for dyn ErasedPtr { + fn eq(&self, other: &Self) -> bool { + self.equals(other) + } } impl ErasedPtr for Ptr @@ -1043,42 +1062,25 @@ where T: ByteRepr + 'static, Ptr: PartialEq, { - fn pointee_type_id(&self) -> std::any::TypeId { - std::any::TypeId::of::() - } - - fn memcpy(&self, src: &dyn ErasedPtr, len: usize) { - if self.pointee_type_id() != src.pointee_type_id() { - panic!("memcpy: type mismatch"); - } - let src_ptr = src - .as_any() - .downcast_ref::>() - .expect("memcpy: downcast to Ptr failed"); - let dst_bytes: Ptr = self.reinterpret_cast(); - let src_bytes: Ptr = src_ptr.reinterpret_cast(); - dst_bytes.memcpy(&src_bytes, len); + fn as_bytes(&self) -> Ptr { + self.reinterpret_cast::() } fn as_any(&self) -> &dyn std::any::Any { self } - fn equals(&self, other: &dyn ErasedPtr) -> Option { - if self.pointee_type_id() != other.pointee_type_id() { - return None; - } - - if let Some(other_ptr) = other.as_any().downcast_ref::>() { - return Some(self == other_ptr); - } - - None + fn equals(&self, other: &dyn ErasedPtr) -> bool { + other.as_any().downcast_ref::>() == Some(self) } fn is_null(&self) -> bool { Ptr::is_null(self) } + + fn address(&self) -> usize { + self.kind.address().wrapping_add(self.byte_offset()) + } } #[derive(Clone)] @@ -1109,64 +1111,36 @@ impl AnyPtr { } pub fn reinterpret_cast(&self) -> Ptr { - macro_rules! try_src { - ($ty:ty) => {{ - if let Some(p) = self.cast::<$ty>() { - return p.reinterpret_cast::(); - } - if let Some(pv) = self.cast::>() { - return pv.reinterpret_cast::(); - } - }}; + if self.ptr.is_null() { + return Ptr::::null(); } - - try_src!(u8); - try_src!(i8); - try_src!(u16); - try_src!(i16); - try_src!(u32); - try_src!(i32); - try_src!(u64); - try_src!(i64); - try_src!(usize); - try_src!(isize); - - panic!("reinterpret_cast: unsupported AnyPtr source"); + if let Some(p) = self.ptr.as_any().downcast_ref::>() { + return p.clone(); + } + self.ptr.as_bytes().reinterpret_cast::() } } impl PartialEq for AnyPtr { fn eq(&self, other: &Self) -> bool { - let lhs: &dyn ErasedPtr = self.ptr.as_ref(); - let rhs: &dyn ErasedPtr = other.ptr.as_ref(); - - lhs.equals(rhs).unwrap_or_default() + *self.ptr == *other.ptr } } impl AnyPtr { pub fn memcpy(&self, src: &AnyPtr, len: usize) { - let dst_erased = &*self.ptr; - let src_erased = &*src.ptr; - - if dst_erased.pointee_type_id() == src_erased.pointee_type_id() { - dst_erased.memcpy(src_erased, len); - return; - } - - let dst_u8: Ptr = self.reinterpret_cast(); - let src_u8: Ptr = src.reinterpret_cast(); + let dst_u8 = self.ptr.as_bytes(); + let src_u8 = src.ptr.as_bytes(); dst_u8.memcpy(&src_u8, len); } pub fn memset(&self, value: u8, num: usize) { - let dst_u8: Ptr = self.reinterpret_cast(); - dst_u8.memset(value, num); + self.ptr.as_bytes().memset(value, num); } pub fn memcmp(&self, other: &AnyPtr, len: usize) -> i32 { - let a: Ptr = self.reinterpret_cast(); - let b: Ptr = other.reinterpret_cast(); + let a = self.ptr.as_bytes(); + let b = other.ptr.as_bytes(); a.memcmp(&b, len) } } @@ -1244,7 +1218,86 @@ impl AsPointerDyn for Rc> { } } -impl ByteRepr for Ptr {} +thread_local! { + // address -> the live pointer at that address (key 0 is null, never stored) + static PTR_REGISTRY: RefCell> = RefCell::new(HashMap::new()); +} + +fn register_ptr(ptr: AnyPtr) -> usize { + let addr = ptr.ptr.address(); + PTR_REGISTRY.with(|reg| reg.borrow_mut().insert(addr, ptr)); + addr +} + +fn lookup_ptr(addr: usize) -> AnyPtr { + PTR_REGISTRY.with(|reg| { + reg.borrow() + .get(&addr) + .cloned() + .expect("ub: unregistered pointer") + }) +} + +fn ptr_to_bytes(addr: usize, buf: &mut [u8]) { + buf[..std::mem::size_of::()].copy_from_slice(&addr.to_ne_bytes()); +} + +fn ptr_from_bytes(buf: &[u8]) -> usize { + let mut a = [0u8; std::mem::size_of::()]; + a.copy_from_slice(&buf[..std::mem::size_of::()]); + usize::from_ne_bytes(a) +} + +impl ByteRepr for Ptr { + fn byte_size() -> usize { + std::mem::size_of::() + } + + fn to_bytes(&self, buf: &mut [u8]) { + let addr = if self.is_null() { 0 } else { register_ptr(self.clone().to_any()) }; + ptr_to_bytes(addr, buf); + } + + fn from_bytes(buf: &[u8]) -> Self { + let addr = ptr_from_bytes(buf); + if addr == 0 { + return Ptr::null(); + } + lookup_ptr(addr).reinterpret_cast::() + } +} + +impl ByteRepr for AnyPtr { + fn byte_size() -> usize { + std::mem::size_of::() + } + + fn to_bytes(&self, buf: &mut [u8]) { + let addr = if self.ptr.is_null() { 0 } else { register_ptr(self.clone()) }; + ptr_to_bytes(addr, buf); + } + + fn from_bytes(buf: &[u8]) -> Self { + let addr = ptr_from_bytes(buf); + if addr == 0 { + return AnyPtr::default(); + } + lookup_ptr(addr) + } +} + +impl Ptr { + pub(crate) fn reinterpreted_sized( + alloc: Rc, + byte_offset: usize, + byte_size: usize, + ) -> Self { + Ptr { + offset: byte_offset, + kind: PtrKind::Reinterpreted(Rc::new(ReinterpretedView { alloc, byte_size })), + } + } +} #[cfg(test)] mod tests { diff --git a/libcc2rs/src/reinterpret.rs b/libcc2rs/src/reinterpret.rs index 452b35de..afb34376 100644 --- a/libcc2rs/src/reinterpret.rs +++ b/libcc2rs/src/reinterpret.rs @@ -4,20 +4,39 @@ use std::{cell::RefCell, rc::Weak}; pub trait ByteRepr: 'static { + fn byte_size() -> usize + where + Self: Sized, + { + panic!( + "byte_size is not implemented for {}", + std::any::type_name::() + ) + } fn to_bytes(&self, _buf: &mut [u8]) { - panic!("ByteRepr not supported for this type"); + panic!( + "to_bytes is not implemented for {}", + std::any::type_name::() + ) } fn from_bytes(_buf: &[u8]) -> Self where Self: Sized, { - panic!("ByteRepr not supported for this type"); + panic!( + "from_bytes is not implemented for {}", + std::any::type_name::() + ) } } macro_rules! impl_byte_repr { ($ty:ty) => { impl ByteRepr for $ty { + #[inline] + fn byte_size() -> usize { + std::mem::size_of::<$ty>() + } #[inline] fn to_bytes(&self, buf: &mut [u8]) { buf.copy_from_slice(&self.to_ne_bytes()); @@ -46,6 +65,10 @@ impl_byte_repr!(f32); impl_byte_repr!(f64); impl ByteRepr for bool { + #[inline] + fn byte_size() -> usize { + 1 + } #[inline] fn to_bytes(&self, buf: &mut [u8]) { buf[0] = *self as u8; @@ -62,7 +85,22 @@ impl ByteRepr for Vec {} impl ByteRepr for Option {} impl ByteRepr for std::rc::Rc {} impl ByteRepr for std::cell::RefCell {} -impl ByteRepr for Box<[T]> {} +impl ByteRepr for Box<[T]> { + fn to_bytes(&self, buf: &mut [u8]) { + let size = std::mem::size_of::(); + for (i, elem) in self.iter().enumerate() { + elem.to_bytes(&mut buf[i * size..(i + 1) * size]); + } + } + fn from_bytes(buf: &[u8]) -> Self { + let size = std::mem::size_of::(); + let n = buf.len() / size; + (0..n) + .map(|i| T::from_bytes(&buf[i * size..(i + 1) * size])) + .collect::>() + .into_boxed_slice() + } +} impl ByteRepr for Box {} impl ByteRepr for *const T {} impl ByteRepr for *mut T {} @@ -83,7 +121,7 @@ pub trait OriginalAlloc { // Only serializes the overlapping elements, not the whole slice. fn slice_read_bytes(slice: &[S], byte_offset: usize, buf: &mut [u8]) { let len = buf.len(); - let elem_size = std::mem::size_of::(); + let elem_size = S::byte_size(); let first_elem = byte_offset / elem_size; let last_elem = (byte_offset + len).div_ceil(elem_size); let tmp_len = (last_elem - first_elem) * elem_size; @@ -98,7 +136,7 @@ fn slice_read_bytes(slice: &[S], byte_offset: usize, buf: &mut [u8] // Write `data` at `byte_offset` into a slice of S elements. // Only deserializes/reserializes the overlapping elements. fn slice_write_bytes(slice: &mut [S], byte_offset: usize, data: &[u8]) { - let elem_size = std::mem::size_of::(); + let elem_size = S::byte_size(); let mut elem_buf = vec![0u8; elem_size]; let first_elem = byte_offset / elem_size; let num_elem = data.len().div_ceil(elem_size); @@ -136,7 +174,7 @@ impl OriginalAlloc for SingleOriginalAlloc { } fn total_byte_len(&self) -> usize { - std::mem::size_of::() + T::byte_size() } fn address(&self) -> usize { @@ -190,7 +228,7 @@ impl OriginalAlloc for SliceOriginalAlloc { fn total_byte_len(&self) -> usize { let rc = self.weak.upgrade().expect("ub: dangling pointer"); let val = rc.borrow(); - std::mem::size_of_val(val.as_slice()) + val.as_slice().len() * ::byte_size() } fn address(&self) -> usize { diff --git a/libcc2rs/src/union.rs b/libcc2rs/src/union.rs new file mode 100644 index 00000000..f3d17ab7 --- /dev/null +++ b/libcc2rs/src/union.rs @@ -0,0 +1,45 @@ +// Copyright (c) 2022-present INESC-ID. +// Distributed under the MIT license that can be found in the LICENSE file. + +use std::{cell::RefCell, rc::Rc}; + +use crate::Ptr; +use crate::reinterpret::{ByteRepr, OriginalAlloc, SliceOriginalAlloc}; + +pub struct UnionStorage { + bytes: Rc>>, +} + +impl UnionStorage { + pub fn new(size: usize) -> Self { + UnionStorage { + bytes: Rc::new(RefCell::new(vec![0u8; size])), + } + } + + pub fn reinterpret_sized(&self, start: usize, end: usize) -> Ptr { + let alloc: Rc = Rc::new(SliceOriginalAlloc { + weak: Rc::downgrade(&self.bytes), + }); + Ptr::reinterpreted_sized(alloc, start, end - start) + } +} + +impl Clone for UnionStorage { + fn clone(&self) -> Self { + UnionStorage { + bytes: Rc::new(RefCell::new(self.bytes.borrow().clone())), + } + } +} + +impl ByteRepr for UnionStorage { + fn to_bytes(&self, buf: &mut [u8]) { + buf.copy_from_slice(&self.bytes.borrow()); + } + fn from_bytes(buf: &[u8]) -> Self { + UnionStorage { + bytes: Rc::new(RefCell::new(buf.to_vec())), + } + } +} diff --git a/tests/multi-file/cross_tu_anon_enum_collision/out/refcount/cross_tu_anon_enum_collision.rs b/tests/multi-file/cross_tu_anon_enum_collision/out/refcount/cross_tu_anon_enum_collision.rs index c7edae33..a7d41726 100644 --- a/tests/multi-file/cross_tu_anon_enum_collision/out/refcount/cross_tu_anon_enum_collision.rs +++ b/tests/multi-file/cross_tu_anon_enum_collision/out/refcount/cross_tu_anon_enum_collision.rs @@ -20,6 +20,17 @@ impl From for anon_0 { } } libcc2rs::impl_enum_inc_dec!(anon_0); +impl ByteRepr for anon_0 { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} pub fn a_value_1() -> i32 { let x: Value = Rc::new(RefCell::new(0)); (*x.borrow_mut()) |= (anon_0::ALPHA as i32); @@ -47,6 +58,17 @@ impl From for anon_3 { } } libcc2rs::impl_enum_inc_dec!(anon_3); +impl ByteRepr for anon_3 { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} pub fn b_value_2() -> i32 { let x: Value = Rc::new(RefCell::new(0)); (*x.borrow_mut()) |= (anon_3::BETA as i32); diff --git a/tests/multi-file/cross_tu_tag_collision/out/refcount/cross_tu_tag_collision.rs b/tests/multi-file/cross_tu_tag_collision/out/refcount/cross_tu_tag_collision.rs index 5fd97a8f..f68bcfba 100644 --- a/tests/multi-file/cross_tu_tag_collision/out/refcount/cross_tu_tag_collision.rs +++ b/tests/multi-file/cross_tu_tag_collision/out/refcount/cross_tu_tag_collision.rs @@ -11,6 +11,9 @@ pub struct widget { pub id: Value, } impl ByteRepr for widget { + fn byte_size() -> usize { + 4 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.id.borrow()).to_bytes(&mut buf[0..4]); } @@ -51,6 +54,17 @@ impl From for widget_enum { } } libcc2rs::impl_enum_inc_dec!(widget_enum); +impl ByteRepr for widget_enum { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} pub fn b_value_1() -> i32 { let w: Value = Rc::new(RefCell::new(widget_enum::WIDGET_C)); return ((*w.borrow()) as i32).clone(); diff --git a/tests/multi-file/opaque_forward_decl/out/refcount/opaque_forward_decl.rs b/tests/multi-file/opaque_forward_decl/out/refcount/opaque_forward_decl.rs index db3db41a..ffd206e2 100644 --- a/tests/multi-file/opaque_forward_decl/out/refcount/opaque_forward_decl.rs +++ b/tests/multi-file/opaque_forward_decl/out/refcount/opaque_forward_decl.rs @@ -11,7 +11,21 @@ pub struct container { pub p: Value>, pub x: Value, } -impl ByteRepr for container {} +impl ByteRepr for container { + fn byte_size() -> usize { + 16 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.p.borrow()).to_bytes(&mut buf[0..8]); + (*self.x.borrow()).to_bytes(&mut buf[8..12]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + p: Rc::new(RefCell::new(>::from_bytes(&buf[0..8]))), + x: Rc::new(RefCell::new(::from_bytes(&buf[8..12]))), + } + } +} pub fn main() { std::process::exit(main_0()); } @@ -33,3 +47,4 @@ pub fn touch_0(c: Ptr) { (*(*(*c.borrow()).upgrade().deref()).p.borrow()).clone(); } pub struct opaque; +impl ByteRepr for opaque {} diff --git a/tests/ub/out/refcount/enum_out_of_range_cast.rs b/tests/ub/out/refcount/enum_out_of_range_cast.rs index 60538ac8..463b825e 100644 --- a/tests/ub/out/refcount/enum_out_of_range_cast.rs +++ b/tests/ub/out/refcount/enum_out_of_range_cast.rs @@ -24,6 +24,17 @@ impl From for Color { } } libcc2rs::impl_enum_inc_dec!(Color); +impl ByteRepr for Color { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} pub fn main() { std::process::exit(main_0()); } diff --git a/tests/ub/out/refcount/enum_out_of_range_increment.rs b/tests/ub/out/refcount/enum_out_of_range_increment.rs index 4809fa73..7dffcf97 100644 --- a/tests/ub/out/refcount/enum_out_of_range_increment.rs +++ b/tests/ub/out/refcount/enum_out_of_range_increment.rs @@ -24,6 +24,17 @@ impl From for color { } } libcc2rs::impl_enum_inc_dec!(color); +impl ByteRepr for color { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/10_struct.rs b/tests/unit/out/refcount/10_struct.rs index 2bc298dc..52b05821 100644 --- a/tests/unit/out/refcount/10_struct.rs +++ b/tests/unit/out/refcount/10_struct.rs @@ -20,7 +20,21 @@ impl Clone for GraphNode { this } } -impl ByteRepr for GraphNode {} +impl ByteRepr for GraphNode { + fn byte_size() -> usize { + 16 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.dst.borrow()).to_bytes(&mut buf[0..4]); + (*self.next.borrow()).to_bytes(&mut buf[8..16]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + dst: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + next: Rc::new(RefCell::new(>::from_bytes(&buf[8..16]))), + } + } +} #[derive(Default)] pub struct Graph { pub V: Value, @@ -59,7 +73,21 @@ impl Clone for Graph { this } } -impl ByteRepr for Graph {} +impl ByteRepr for Graph { + fn byte_size() -> usize { + 16 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.V.borrow()).to_bytes(&mut buf[0..4]); + (*self.adj.borrow()).to_bytes(&mut buf[8..16]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + V: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + adj: Rc::new(RefCell::new(>>::from_bytes(&buf[8..16]))), + } + } +} pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/addr_of_global.rs b/tests/unit/out/refcount/addr_of_global.rs index 01ddb7f7..e9ee44e9 100644 --- a/tests/unit/out/refcount/addr_of_global.rs +++ b/tests/unit/out/refcount/addr_of_global.rs @@ -19,6 +19,9 @@ impl Clone for Inner { } } impl ByteRepr for Inner { + fn byte_size() -> usize { + 4 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.value.borrow()).to_bytes(&mut buf[0..4]); } @@ -40,7 +43,19 @@ impl Clone for Outer { this } } -impl ByteRepr for Outer {} +impl ByteRepr for Outer { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.p.borrow()).to_bytes(&mut buf[0..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + p: Rc::new(RefCell::new(>::from_bytes(&buf[0..8]))), + } + } +} thread_local!( pub static alpha_0: Value = Rc::new(RefCell::new(Inner { value: Rc::new(RefCell::new(1)), diff --git a/tests/unit/out/refcount/anonymous-struct.rs b/tests/unit/out/refcount/anonymous-struct.rs index fcd7db80..ad257c16 100644 --- a/tests/unit/out/refcount/anonymous-struct.rs +++ b/tests/unit/out/refcount/anonymous-struct.rs @@ -21,6 +21,9 @@ impl Clone for Outer_Named { } } impl ByteRepr for Outer_Named { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.a.borrow()).to_bytes(&mut buf[0..4]); (*self.b.borrow()).to_bytes(&mut buf[4..8]); @@ -47,6 +50,9 @@ impl Clone for anon_0 { } } impl ByteRepr for anon_0 { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.c.borrow()).to_bytes(&mut buf[0..4]); (*self.d.borrow()).to_bytes(&mut buf[4..8]); @@ -73,6 +79,9 @@ impl Clone for anon_1 { } } impl ByteRepr for anon_1 { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.g.borrow()).to_bytes(&mut buf[0..4]); (*self.h.borrow()).to_bytes(&mut buf[4..8]); @@ -99,6 +108,9 @@ impl Clone for anon_2 { } } impl ByteRepr for anon_2 { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.e.borrow()).to_bytes(&mut buf[0..4]); (*self.f.borrow()).to_bytes(&mut buf[4..8]); @@ -123,6 +135,9 @@ impl Clone for anon_4 { } } impl ByteRepr for anon_4 { + fn byte_size() -> usize { + 4 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.j.borrow()).to_bytes(&mut buf[0..4]); } @@ -145,6 +160,9 @@ impl Clone for anon_5 { } } impl ByteRepr for anon_5 { + fn byte_size() -> usize { + 4 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.k.borrow()).to_bytes(&mut buf[0..4]); } @@ -170,7 +188,23 @@ impl Clone for anon_3 { this } } -impl ByteRepr for anon_3 {} +impl ByteRepr for anon_3 { + fn byte_size() -> usize { + 12 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.i.borrow()).to_bytes(&mut buf[0..4]); + (*self.inner_named.borrow()).to_bytes(&mut buf[4..8]); + (*self.anon_5.borrow()).to_bytes(&mut buf[8..12]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + i: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + inner_named: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + anon_5: Rc::new(RefCell::new(::from_bytes(&buf[8..12]))), + } + } +} #[derive(Default)] pub struct Outer { pub named: Value, @@ -191,7 +225,27 @@ impl Clone for Outer { this } } -impl ByteRepr for Outer {} +impl ByteRepr for Outer { + fn byte_size() -> usize { + 44 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.named.borrow()).to_bytes(&mut buf[0..8]); + (*self.anonymous_named_0.borrow()).to_bytes(&mut buf[8..16]); + (*self.anonymous_named_1.borrow()).to_bytes(&mut buf[16..24]); + (*self.anon_2.borrow()).to_bytes(&mut buf[24..32]); + (*self.anon_3.borrow()).to_bytes(&mut buf[32..44]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + named: Rc::new(RefCell::new(::from_bytes(&buf[0..8]))), + anonymous_named_0: Rc::new(RefCell::new(::from_bytes(&buf[8..16]))), + anonymous_named_1: Rc::new(RefCell::new(::from_bytes(&buf[16..24]))), + anon_2: Rc::new(RefCell::new(::from_bytes(&buf[24..32]))), + anon_3: Rc::new(RefCell::new(::from_bytes(&buf[32..44]))), + } + } +} pub fn main() { std::process::exit(main_0()); } @@ -274,6 +328,9 @@ fn main_0() -> i32 { } } impl ByteRepr for anon_6 { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.x.borrow()).to_bytes(&mut buf[0..4]); (*self.z.borrow()).to_bytes(&mut buf[4..8]); diff --git a/tests/unit/out/refcount/anonymous-struct_c.rs b/tests/unit/out/refcount/anonymous-struct_c.rs index 23ce8df8..970d6e99 100644 --- a/tests/unit/out/refcount/anonymous-struct_c.rs +++ b/tests/unit/out/refcount/anonymous-struct_c.rs @@ -12,6 +12,9 @@ pub struct Named { pub b: Value, } impl ByteRepr for Named { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.a.borrow()).to_bytes(&mut buf[0..4]); (*self.b.borrow()).to_bytes(&mut buf[4..8]); @@ -29,6 +32,9 @@ pub struct anon_0 { pub d: Value, } impl ByteRepr for anon_0 { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.c.borrow()).to_bytes(&mut buf[0..4]); (*self.d.borrow()).to_bytes(&mut buf[4..8]); @@ -46,6 +52,9 @@ pub struct anon_1 { pub h: Value, } impl ByteRepr for anon_1 { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.g.borrow()).to_bytes(&mut buf[0..4]); (*self.h.borrow()).to_bytes(&mut buf[4..8]); @@ -63,6 +72,9 @@ pub struct anon_2 { pub f: Value, } impl ByteRepr for anon_2 { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.e.borrow()).to_bytes(&mut buf[0..4]); (*self.f.borrow()).to_bytes(&mut buf[4..8]); @@ -79,6 +91,9 @@ pub struct anon_4 { pub j: Value, } impl ByteRepr for anon_4 { + fn byte_size() -> usize { + 4 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.j.borrow()).to_bytes(&mut buf[0..4]); } @@ -93,6 +108,9 @@ pub struct anon_5 { pub k: Value, } impl ByteRepr for anon_5 { + fn byte_size() -> usize { + 4 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.k.borrow()).to_bytes(&mut buf[0..4]); } @@ -108,7 +126,23 @@ pub struct anon_3 { pub inner_named: Value, pub anon_5: Value, } -impl ByteRepr for anon_3 {} +impl ByteRepr for anon_3 { + fn byte_size() -> usize { + 12 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.i.borrow()).to_bytes(&mut buf[0..4]); + (*self.inner_named.borrow()).to_bytes(&mut buf[4..8]); + (*self.anon_5.borrow()).to_bytes(&mut buf[8..12]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + i: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + inner_named: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + anon_5: Rc::new(RefCell::new(::from_bytes(&buf[8..12]))), + } + } +} #[derive(Default)] pub struct Outer { pub named: Value, @@ -117,7 +151,27 @@ pub struct Outer { pub anon_2: Value, pub anon_3: Value, } -impl ByteRepr for Outer {} +impl ByteRepr for Outer { + fn byte_size() -> usize { + 44 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.named.borrow()).to_bytes(&mut buf[0..8]); + (*self.anon0.borrow()).to_bytes(&mut buf[8..16]); + (*self.anon1.borrow()).to_bytes(&mut buf[16..24]); + (*self.anon_2.borrow()).to_bytes(&mut buf[24..32]); + (*self.anon_3.borrow()).to_bytes(&mut buf[32..44]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + named: Rc::new(RefCell::new(::from_bytes(&buf[0..8]))), + anon0: Rc::new(RefCell::new(::from_bytes(&buf[8..16]))), + anon1: Rc::new(RefCell::new(::from_bytes(&buf[16..24]))), + anon_2: Rc::new(RefCell::new(::from_bytes(&buf[24..32]))), + anon_3: Rc::new(RefCell::new(::from_bytes(&buf[32..44]))), + } + } +} pub fn main() { std::process::exit(main_0()); } @@ -176,6 +230,9 @@ fn main_0() -> i32 { pub z: Value, } impl ByteRepr for anon_6 { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.x.borrow()).to_bytes(&mut buf[0..4]); (*self.z.borrow()).to_bytes(&mut buf[4..8]); diff --git a/tests/unit/out/refcount/anonymous_enum.rs b/tests/unit/out/refcount/anonymous_enum.rs index 25de7201..f248358e 100644 --- a/tests/unit/out/refcount/anonymous_enum.rs +++ b/tests/unit/out/refcount/anonymous_enum.rs @@ -22,6 +22,17 @@ impl From for anon_0 { } } libcc2rs::impl_enum_inc_dec!(anon_0); +impl ByteRepr for anon_0 { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} #[derive(Clone, Copy, PartialEq, Debug, Default)] enum anon_1 { #[default] @@ -38,6 +49,17 @@ impl From for anon_1 { } } libcc2rs::impl_enum_inc_dec!(anon_1); +impl ByteRepr for anon_1 { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} #[derive(Default)] pub struct S { pub a: Value, @@ -51,6 +73,9 @@ impl Clone for S { } } impl ByteRepr for S { + fn byte_size() -> usize { + 4 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.a.borrow()).to_bytes(&mut buf[0..4]); } @@ -76,6 +101,17 @@ impl From for TdEnum { } } libcc2rs::impl_enum_inc_dec!(TdEnum); +impl ByteRepr for TdEnum { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} #[derive(Clone, Copy, PartialEq, Debug, Default)] enum anon_2 { #[default] @@ -92,6 +128,17 @@ impl From for anon_2 { } } libcc2rs::impl_enum_inc_dec!(anon_2); +impl ByteRepr for anon_2 { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} #[derive(Default)] pub struct WithAnonField { pub a: Value, @@ -106,7 +153,21 @@ impl Clone for WithAnonField { this } } -impl ByteRepr for WithAnonField {} +impl ByteRepr for WithAnonField { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.a.borrow()).to_bytes(&mut buf[0..4]); + (*self.field.borrow()).to_bytes(&mut buf[4..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + a: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + field: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + } + } +} pub fn main() { std::process::exit(main_0()); } @@ -127,6 +188,17 @@ fn main_0() -> i32 { } } libcc2rs::impl_enum_inc_dec!(anon_3); + impl ByteRepr for anon_3 { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } + }; assert!(((anon_0::FIRST_A as i32) != (anon_0::FIRST_B as i32))); assert!(((anon_1::SECOND_A as i32) != (anon_1::SECOND_B as i32))); assert!(((anon_3::THIRD_A as i32) != (anon_3::THIRD_B as i32))); diff --git a/tests/unit/out/refcount/anonymous_enum_c.rs b/tests/unit/out/refcount/anonymous_enum_c.rs index 772ea6e5..55d55567 100644 --- a/tests/unit/out/refcount/anonymous_enum_c.rs +++ b/tests/unit/out/refcount/anonymous_enum_c.rs @@ -22,6 +22,17 @@ impl From for anon_0 { } } libcc2rs::impl_enum_inc_dec!(anon_0); +impl ByteRepr for anon_0 { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} #[derive(Clone, Copy, PartialEq, Debug, Default)] enum anon_1 { #[default] @@ -38,11 +49,25 @@ impl From for anon_1 { } } libcc2rs::impl_enum_inc_dec!(anon_1); +impl ByteRepr for anon_1 { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} #[derive(Default)] pub struct S { pub a: Value, } impl ByteRepr for S { + fn byte_size() -> usize { + 4 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.a.borrow()).to_bytes(&mut buf[0..4]); } @@ -68,6 +93,17 @@ impl From for TdEnum_enum { } } libcc2rs::impl_enum_inc_dec!(TdEnum_enum); +impl ByteRepr for TdEnum_enum { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} #[derive(Clone, Copy, PartialEq, Debug, Default)] enum anon_2 { #[default] @@ -84,12 +120,37 @@ impl From for anon_2 { } } libcc2rs::impl_enum_inc_dec!(anon_2); +impl ByteRepr for anon_2 { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} #[derive(Default)] pub struct WithAnonField { pub a: Value, pub field: Value, } -impl ByteRepr for WithAnonField {} +impl ByteRepr for WithAnonField { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.a.borrow()).to_bytes(&mut buf[0..4]); + (*self.field.borrow()).to_bytes(&mut buf[4..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + a: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + field: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + } + } +} pub fn main() { std::process::exit(main_0()); } @@ -110,6 +171,17 @@ fn main_0() -> i32 { } } libcc2rs::impl_enum_inc_dec!(anon_3); + impl ByteRepr for anon_3 { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } + }; assert!(((((anon_0::FIRST_A as i32) != (anon_0::FIRST_B as i32)) as i32) != 0)); assert!(((((anon_1::SECOND_A as i32) != (anon_1::SECOND_B as i32)) as i32) != 0)); assert!(((((anon_3::THIRD_A as i32) != (anon_3::THIRD_B as i32)) as i32) != 0)); diff --git a/tests/unit/out/refcount/array_const_init.rs b/tests/unit/out/refcount/array_const_init.rs index 784f3a73..7a2cf78d 100644 --- a/tests/unit/out/refcount/array_const_init.rs +++ b/tests/unit/out/refcount/array_const_init.rs @@ -25,7 +25,23 @@ impl Default for S { } } } -impl ByteRepr for S {} +impl ByteRepr for S { + fn byte_size() -> usize { + 20 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.head.borrow()).to_bytes(&mut buf[0..4]); + (*self.tail.borrow()).to_bytes(&mut buf[4..16]); + (*self.buf.borrow()).to_bytes(&mut buf[16..20]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + head: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + tail: Rc::new(RefCell::new(>::from_bytes(&buf[4..16]))), + buf: Rc::new(RefCell::new(>::from_bytes(&buf[16..20]))), + } + } +} thread_local!( pub static s_0: Value = Rc::new(RefCell::new(S { head: Rc::new(RefCell::new(5)), diff --git a/tests/unit/out/refcount/array_of_noncopy_struct.rs b/tests/unit/out/refcount/array_of_noncopy_struct.rs index 4af56349..0c91af6d 100644 --- a/tests/unit/out/refcount/array_of_noncopy_struct.rs +++ b/tests/unit/out/refcount/array_of_noncopy_struct.rs @@ -20,7 +20,21 @@ impl Clone for NonCopy { this } } -impl ByteRepr for NonCopy {} +impl ByteRepr for NonCopy { + fn byte_size() -> usize { + 32 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.data.borrow()).to_bytes(&mut buf[0..24]); + (*self.tag.borrow()).to_bytes(&mut buf[24..28]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + data: Rc::new(RefCell::new(>::from_bytes(&buf[0..24]))), + tag: Rc::new(RefCell::new(::from_bytes(&buf[24..28]))), + } + } +} pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/bool_condition_enum.rs b/tests/unit/out/refcount/bool_condition_enum.rs index 1d7dc853..ddc111e8 100644 --- a/tests/unit/out/refcount/bool_condition_enum.rs +++ b/tests/unit/out/refcount/bool_condition_enum.rs @@ -24,6 +24,17 @@ impl From for Code { } } libcc2rs::impl_enum_inc_dec!(Code); +impl ByteRepr for Code { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/bool_condition_enum_c.rs b/tests/unit/out/refcount/bool_condition_enum_c.rs index f84c1a88..4dc973eb 100644 --- a/tests/unit/out/refcount/bool_condition_enum_c.rs +++ b/tests/unit/out/refcount/bool_condition_enum_c.rs @@ -24,6 +24,17 @@ impl From for Code { } } libcc2rs::impl_enum_inc_dec!(Code); +impl ByteRepr for Code { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/bool_condition_logical.rs b/tests/unit/out/refcount/bool_condition_logical.rs index 9b340849..f54fa8d9 100644 --- a/tests/unit/out/refcount/bool_condition_logical.rs +++ b/tests/unit/out/refcount/bool_condition_logical.rs @@ -24,6 +24,17 @@ impl From for Code { } } libcc2rs::impl_enum_inc_dec!(Code); +impl ByteRepr for Code { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} thread_local!( pub static side_effect_0: Value = Rc::new(RefCell::new(0)); ); diff --git a/tests/unit/out/refcount/bool_condition_logical_c.rs b/tests/unit/out/refcount/bool_condition_logical_c.rs index a878ce93..c7e77840 100644 --- a/tests/unit/out/refcount/bool_condition_logical_c.rs +++ b/tests/unit/out/refcount/bool_condition_logical_c.rs @@ -24,6 +24,17 @@ impl From for Code { } } libcc2rs::impl_enum_inc_dec!(Code); +impl ByteRepr for Code { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} thread_local!( pub static side_effect_0: Value = Rc::new(RefCell::new(0)); ); diff --git a/tests/unit/out/refcount/bounded_struct_ptr.rs b/tests/unit/out/refcount/bounded_struct_ptr.rs index 477a71a6..6da5e2fb 100644 --- a/tests/unit/out/refcount/bounded_struct_ptr.rs +++ b/tests/unit/out/refcount/bounded_struct_ptr.rs @@ -21,6 +21,9 @@ impl Clone for Foo { } } impl ByteRepr for Foo { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.x1.borrow()).to_bytes(&mut buf[0..4]); (*self.x2.borrow()).to_bytes(&mut buf[4..8]); diff --git a/tests/unit/out/refcount/bst.rs b/tests/unit/out/refcount/bst.rs index bead4d4a..4fd8a5a3 100644 --- a/tests/unit/out/refcount/bst.rs +++ b/tests/unit/out/refcount/bst.rs @@ -22,7 +22,23 @@ impl Clone for node_t { this } } -impl ByteRepr for node_t {} +impl ByteRepr for node_t { + fn byte_size() -> usize { + 24 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.left.borrow()).to_bytes(&mut buf[0..8]); + (*self.right.borrow()).to_bytes(&mut buf[8..16]); + (*self.value.borrow()).to_bytes(&mut buf[16..20]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + left: Rc::new(RefCell::new(>::from_bytes(&buf[0..8]))), + right: Rc::new(RefCell::new(>::from_bytes(&buf[8..16]))), + value: Rc::new(RefCell::new(::from_bytes(&buf[16..20]))), + } + } +} pub fn find_0(node: Ptr, value: i32) -> Ptr { let node: Value> = Rc::new(RefCell::new(node)); let value: Value = Rc::new(RefCell::new(value)); diff --git a/tests/unit/out/refcount/c_struct.rs b/tests/unit/out/refcount/c_struct.rs index 0549baab..174f742b 100644 --- a/tests/unit/out/refcount/c_struct.rs +++ b/tests/unit/out/refcount/c_struct.rs @@ -12,6 +12,9 @@ pub struct Point { pub y: Value, } impl ByteRepr for Point { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.x.borrow()).to_bytes(&mut buf[0..4]); (*self.y.borrow()).to_bytes(&mut buf[4..8]); @@ -28,13 +31,41 @@ pub struct Line { pub start: Value, pub end: Value, } -impl ByteRepr for Line {} +impl ByteRepr for Line { + fn byte_size() -> usize { + 16 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.start.borrow()).to_bytes(&mut buf[0..8]); + (*self.end.borrow()).to_bytes(&mut buf[8..16]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + start: Rc::new(RefCell::new(::from_bytes(&buf[0..8]))), + end: Rc::new(RefCell::new(::from_bytes(&buf[8..16]))), + } + } +} #[derive(Default)] pub struct Node { pub value: Value, pub next: Value>, } -impl ByteRepr for Node {} +impl ByteRepr for Node { + fn byte_size() -> usize { + 16 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.value.borrow()).to_bytes(&mut buf[0..4]); + (*self.next.borrow()).to_bytes(&mut buf[8..16]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + value: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + next: Rc::new(RefCell::new(>::from_bytes(&buf[8..16]))), + } + } +} #[derive(Clone, Copy, PartialEq, Debug, Default)] enum Color { #[default] @@ -53,12 +84,26 @@ impl From for Color { } } libcc2rs::impl_enum_inc_dec!(Color); +impl ByteRepr for Color { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} #[derive(Default)] pub struct Inner { pub a: Value, pub b: Value, } impl ByteRepr for Inner { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.a.borrow()).to_bytes(&mut buf[0..4]); (*self.b.borrow()).to_bytes(&mut buf[4..8]); @@ -76,7 +121,23 @@ pub struct Container { pub color: Value, pub count: Value, } -impl ByteRepr for Container {} +impl ByteRepr for Container { + fn byte_size() -> usize { + 16 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.inner.borrow()).to_bytes(&mut buf[0..8]); + (*self.color.borrow()).to_bytes(&mut buf[8..12]); + (*self.count.borrow()).to_bytes(&mut buf[12..16]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + inner: Rc::new(RefCell::new(::from_bytes(&buf[0..8]))), + color: Rc::new(RefCell::new(::from_bytes(&buf[8..12]))), + count: Rc::new(RefCell::new(::from_bytes(&buf[12..16]))), + } + } +} pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/class.rs b/tests/unit/out/refcount/class.rs index 6bed63d3..ed4161fc 100644 --- a/tests/unit/out/refcount/class.rs +++ b/tests/unit/out/refcount/class.rs @@ -56,6 +56,9 @@ impl Clone for Pair { } } impl ByteRepr for Pair { + fn byte_size() -> usize { + 8 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.first.borrow()).to_bytes(&mut buf[0..4]); (*self.second.borrow()).to_bytes(&mut buf[4..8]); @@ -89,7 +92,21 @@ impl Clone for Route { this } } -impl ByteRepr for Route {} +impl ByteRepr for Route { + fn byte_size() -> usize { + 16 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.path.borrow()).to_bytes(&mut buf[0..8]); + (*self.cost.borrow()).to_bytes(&mut buf[8..16]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + path: Rc::new(RefCell::new(::from_bytes(&buf[0..8]))), + cost: Rc::new(RefCell::new(::from_bytes(&buf[8..16]))), + } + } +} pub fn RandomRoute_0(route: Ptr) -> i32 { if (((*(*(*route.upgrade().deref()).path.borrow()).first.borrow()) % 2) != 0) { return ({ diff --git a/tests/unit/out/refcount/class_templates.rs b/tests/unit/out/refcount/class_templates.rs index 3cbce86e..183fbd41 100644 --- a/tests/unit/out/refcount/class_templates.rs +++ b/tests/unit/out/refcount/class_templates.rs @@ -42,7 +42,19 @@ impl Clone for MyContainer_int_ { this } } -impl ByteRepr for MyContainer_int_ {} +impl ByteRepr for MyContainer_int_ { + fn byte_size() -> usize { + 24 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.vec_.borrow()).to_bytes(&mut buf[0..24]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + vec_: Rc::new(RefCell::new(>::from_bytes(&buf[0..24]))), + } + } +} #[derive(Default)] pub struct MyContainer_char_ { vec_: Value>, @@ -79,7 +91,19 @@ impl Clone for MyContainer_char_ { this } } -impl ByteRepr for MyContainer_char_ {} +impl ByteRepr for MyContainer_char_ { + fn byte_size() -> usize { + 24 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.vec_.borrow()).to_bytes(&mut buf[0..24]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + vec_: Rc::new(RefCell::new(>::from_bytes(&buf[0..24]))), + } + } +} #[derive(Default)] pub struct MyContainer_float_ { vec_: Value>, @@ -116,7 +140,19 @@ impl Clone for MyContainer_float_ { this } } -impl ByteRepr for MyContainer_float_ {} +impl ByteRepr for MyContainer_float_ { + fn byte_size() -> usize { + 24 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.vec_.borrow()).to_bytes(&mut buf[0..24]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + vec_: Rc::new(RefCell::new(>::from_bytes(&buf[0..24]))), + } + } +} pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/clone_vs_move.rs b/tests/unit/out/refcount/clone_vs_move.rs index 9f6ee411..1953e3d9 100644 --- a/tests/unit/out/refcount/clone_vs_move.rs +++ b/tests/unit/out/refcount/clone_vs_move.rs @@ -19,6 +19,9 @@ impl Clone for Bar { } } impl ByteRepr for Bar { + fn byte_size() -> usize { + 4 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.w.borrow()).to_bytes(&mut buf[0..4]); } diff --git a/tests/unit/out/refcount/complex_function.rs b/tests/unit/out/refcount/complex_function.rs index 07a300f9..21e1714c 100644 --- a/tests/unit/out/refcount/complex_function.rs +++ b/tests/unit/out/refcount/complex_function.rs @@ -30,6 +30,9 @@ impl Clone for X1 { } } impl ByteRepr for X1 { + fn byte_size() -> usize { + 4 + } fn to_bytes(&self, buf: &mut [u8]) { (*self.v.borrow()).to_bytes(&mut buf[0..4]); } @@ -74,7 +77,19 @@ impl Clone for X3 { this } } -impl ByteRepr for X3 {} +impl ByteRepr for X3 { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.v.borrow()).to_bytes(&mut buf[0..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + v: Rc::new(RefCell::new(>::from_bytes(&buf[0..8]))), + } + } +} #[derive(Default)] pub struct X4 { pub v: Value, @@ -92,7 +107,19 @@ impl Clone for X4 { this } } -impl ByteRepr for X4 {} +impl ByteRepr for X4 { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.v.borrow()).to_bytes(&mut buf[0..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + v: Rc::new(RefCell::new(::from_bytes(&buf[0..8]))), + } + } +} pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/default.rs b/tests/unit/out/refcount/default.rs index 3f2389c5..0a4447a7 100644 --- a/tests/unit/out/refcount/default.rs +++ b/tests/unit/out/refcount/default.rs @@ -45,7 +45,27 @@ impl Default for Pointers { } } } -impl ByteRepr for Pointers {} +impl ByteRepr for Pointers { + fn byte_size() -> usize { + 144 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.x1.borrow()).to_bytes(&mut buf[0..8]); + (*self.x2.borrow()).to_bytes(&mut buf[8..16]); + (*self.x3.borrow()).to_bytes(&mut buf[16..56]); + (*self.x4.borrow()).to_bytes(&mut buf[56..136]); + (*self.x5.borrow()).to_bytes(&mut buf[136..140]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + x1: Rc::new(RefCell::new(>::from_bytes(&buf[0..8]))), + x2: Rc::new(RefCell::new(>::from_bytes(&buf[8..16]))), + x3: Rc::new(RefCell::new(]>>::from_bytes(&buf[16..56]))), + x4: Rc::new(RefCell::new(]>>::from_bytes(&buf[56..136]))), + x5: Rc::new(RefCell::new(::from_bytes(&buf[136..140]))), + } + } +} pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/default_in_statics.rs b/tests/unit/out/refcount/default_in_statics.rs index 7936846d..7636013a 100644 --- a/tests/unit/out/refcount/default_in_statics.rs +++ b/tests/unit/out/refcount/default_in_statics.rs @@ -20,7 +20,21 @@ impl Clone for Inner { this } } -impl ByteRepr for Inner {} +impl ByteRepr for Inner { + fn byte_size() -> usize { + 16 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.v.borrow()).to_bytes(&mut buf[0..4]); + (*self.name.borrow()).to_bytes(&mut buf[8..16]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + v: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + name: Rc::new(RefCell::new(>::from_bytes(&buf[8..16]))), + } + } +} #[derive()] pub struct Outer { pub p1: Value>, @@ -65,7 +79,35 @@ impl Default for Outer { } } } -impl ByteRepr for Outer {} +impl ByteRepr for Outer { + fn byte_size() -> usize { + 88 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.p1.borrow()).to_bytes(&mut buf[0..8]); + (*self.p2.borrow()).to_bytes(&mut buf[8..16]); + (*self.arr.borrow()).to_bytes(&mut buf[16..40]); + (*self.cp.borrow()).to_bytes(&mut buf[40..48]); + (*self.pp.borrow()).to_bytes(&mut buf[48..56]); + (*self.inner.borrow()).to_bytes(&mut buf[56..72]); + (*self.x.borrow()).to_bytes(&mut buf[72..76]); + (*self.fn_.borrow()).to_bytes(&mut buf[80..88]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + p1: Rc::new(RefCell::new(>::from_bytes(&buf[0..8]))), + p2: Rc::new(RefCell::new(>::from_bytes(&buf[8..16]))), + arr: Rc::new(RefCell::new(]>>::from_bytes(&buf[16..40]))), + cp: Rc::new(RefCell::new(>::from_bytes(&buf[40..48]))), + pp: Rc::new(RefCell::new(>>::from_bytes(&buf[48..56]))), + inner: Rc::new(RefCell::new(::from_bytes(&buf[56..72]))), + x: Rc::new(RefCell::new(::from_bytes(&buf[72..76]))), + fn_: Rc::new(RefCell::new( i32>>::from_bytes( + &buf[80..88], + ))), + } + } +} #[derive()] pub struct Foo { pub s1: Value>, @@ -97,7 +139,31 @@ impl Default for Foo { } } } -impl ByteRepr for Foo {} +impl ByteRepr for Foo { + fn byte_size() -> usize { + 40 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.s1.borrow()).to_bytes(&mut buf[0..8]); + (*self.s2.borrow()).to_bytes(&mut buf[8..16]); + (*self.fn1.borrow()).to_bytes(&mut buf[16..24]); + (*self.fn2.borrow()).to_bytes(&mut buf[24..32]); + (*self.n.borrow()).to_bytes(&mut buf[32..36]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + s1: Rc::new(RefCell::new(>::from_bytes(&buf[0..8]))), + s2: Rc::new(RefCell::new(>::from_bytes(&buf[8..16]))), + fn1: Rc::new(RefCell::new( i32>>::from_bytes( + &buf[16..24], + ))), + fn2: Rc::new(RefCell::new( i32>>::from_bytes( + &buf[24..32], + ))), + n: Rc::new(RefCell::new(::from_bytes(&buf[32..36]))), + } + } +} thread_local!( pub static static_fn_0: Value i32>> = Rc::new(RefCell::new(FnPtr::null())); ); diff --git a/tests/unit/out/refcount/doubly_linked_list.rs b/tests/unit/out/refcount/doubly_linked_list.rs index ff45aed2..4b66b546 100644 --- a/tests/unit/out/refcount/doubly_linked_list.rs +++ b/tests/unit/out/refcount/doubly_linked_list.rs @@ -32,7 +32,23 @@ impl Clone for Node { this } } -impl ByteRepr for Node {} +impl ByteRepr for Node { + fn byte_size() -> usize { + 24 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.val.borrow()).to_bytes(&mut buf[0..4]); + (*self.next.borrow()).to_bytes(&mut buf[8..16]); + (*self.prev.borrow()).to_bytes(&mut buf[16..24]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + val: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + next: Rc::new(RefCell::new(>::from_bytes(&buf[8..16]))), + prev: Rc::new(RefCell::new(>::from_bytes(&buf[16..24]))), + } + } +} pub fn Find_0(head: Ptr, idx: i32) -> Ptr { let head: Value> = Rc::new(RefCell::new(head)); let idx: Value = Rc::new(RefCell::new(idx)); diff --git a/tests/unit/out/refcount/enum_default_in_static.rs b/tests/unit/out/refcount/enum_default_in_static.rs index 96f3bd8e..0c8b8760 100644 --- a/tests/unit/out/refcount/enum_default_in_static.rs +++ b/tests/unit/out/refcount/enum_default_in_static.rs @@ -24,12 +24,37 @@ impl From for Mode { } } libcc2rs::impl_enum_inc_dec!(Mode); +impl ByteRepr for Mode { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} #[derive(Default)] pub struct Config { pub count: Value, pub mode: Value, } -impl ByteRepr for Config {} +impl ByteRepr for Config { + fn byte_size() -> usize { + 8 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self.count.borrow()).to_bytes(&mut buf[0..4]); + (*self.mode.borrow()).to_bytes(&mut buf[4..8]); + } + fn from_bytes(buf: &[u8]) -> Self { + Self { + count: Rc::new(RefCell::new(::from_bytes(&buf[0..4]))), + mode: Rc::new(RefCell::new(::from_bytes(&buf[4..8]))), + } + } +} thread_local!( pub static config_0: Value = >::default(); ); diff --git a/tests/unit/out/refcount/enum_increment.rs b/tests/unit/out/refcount/enum_increment.rs index 25a24a2f..a6802f27 100644 --- a/tests/unit/out/refcount/enum_increment.rs +++ b/tests/unit/out/refcount/enum_increment.rs @@ -26,6 +26,17 @@ impl From for color { } } libcc2rs::impl_enum_inc_dec!(color); +impl ByteRepr for color { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} pub fn main() { std::process::exit(main_0()); } diff --git a/tests/unit/out/refcount/enum_int_interop.rs b/tests/unit/out/refcount/enum_int_interop.rs index 01a28cd8..137eacf4 100644 --- a/tests/unit/out/refcount/enum_int_interop.rs +++ b/tests/unit/out/refcount/enum_int_interop.rs @@ -24,6 +24,17 @@ impl From for Color { } } libcc2rs::impl_enum_inc_dec!(Color); +impl ByteRepr for Color { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { + ::from(i32::from_bytes(buf)) + } +} #[derive(Clone, Copy, PartialEq, Debug, Default)] enum Option { #[default] @@ -44,6 +55,17 @@ impl From for Option { } } libcc2rs::impl_enum_inc_dec!(Option); +impl ByteRepr for Option { + fn byte_size() -> usize { + 4 + } + fn to_bytes(&self, buf: &mut [u8]) { + (*self as i32).to_bytes(buf); + } + fn from_bytes(buf: &[u8]) -> Self { +