|
3 | 3 |
|
4 | 4 | #include "converter/models/converter_refcount.h" |
5 | 5 |
|
| 6 | +#include <clang/AST/RecordLayout.h> |
6 | 7 | #include <clang/Basic/OperatorKinds.h> |
7 | 8 |
|
8 | 9 | #include <format> |
@@ -497,10 +498,70 @@ void ConverterRefCount::AddDropTrait(const clang::CXXRecordDecl *decl) { |
497 | 498 | StrCat("}"); |
498 | 499 | } |
499 | 500 |
|
| 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 | + |
500 | 521 | void ConverterRefCount::AddByteReprTrait(const clang::RecordDecl *decl) { |
501 | 522 | 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 | + |
502 | 530 | 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 | + } |
504 | 565 | } |
505 | 566 |
|
506 | 567 | std::string |
|
0 commit comments