From f28da962726a09a8155b4a8bd1700d910f600661 Mon Sep 17 00:00:00 2001 From: Justin King Date: Mon, 5 Oct 2026 15:39:22 -0700 Subject: [PATCH] Remove `cel::Owner`, `cel::Borrower`, `cel::Unique`, `cel::Owned`, and `cel::Borrowed` smart pointers PiperOrigin-RevId: 993946502 --- common/BUILD | 21 - common/memory.h | 1251 ----------------------------- common/memory_test.cc | 466 ----------- common/value.cc | 21 +- internal/BUILD | 4 +- internal/message_equality.cc | 29 +- internal/message_equality_test.cc | 17 +- internal/well_known_types.cc | 50 +- internal/well_known_types.h | 35 +- internal/well_known_types_test.cc | 8 +- 10 files changed, 84 insertions(+), 1818 deletions(-) delete mode 100644 common/memory_test.cc diff --git a/common/BUILD b/common/BUILD index 5b6349624..f75c82f17 100644 --- a/common/BUILD +++ b/common/BUILD @@ -504,12 +504,6 @@ cc_library( hdrs = ["memory.h"], deps = [ ":allocator", - ":arena", - ":data", - ":reference_count", - "//common/internal:metadata", - "//common/internal:reference_count", - "//internal:exceptions", "//internal:to_address", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/base:no_destructor", @@ -520,21 +514,6 @@ cc_library( ], ) -cc_test( - name = "memory_test", - srcs = ["memory_test.cc"], - deps = [ - ":allocator", - ":data", - ":memory", - "//common/internal:reference_count", - "//internal:testing", - "@com_google_absl//absl/base:nullability", - "@com_google_protobuf//:protobuf", - "@com_google_protobuf//:struct_cc_proto", - ], -) - cc_library( name = "memory_testing", testonly = True, diff --git a/common/memory.h b/common/memory.h index 615bce519..967bc57e2 100644 --- a/common/memory.h +++ b/common/memory.h @@ -16,25 +16,16 @@ #define THIRD_PARTY_CEL_CPP_COMMON_MEMORY_H_ #include -#include #include #include #include #include #include "absl/base/attributes.h" -#include "absl/base/macros.h" #include "absl/base/nullability.h" -#include "absl/base/optimization.h" #include "absl/log/absl_check.h" #include "absl/numeric/bits.h" #include "common/allocator.h" -#include "common/arena.h" -#include "common/data.h" -#include "common/internal/metadata.h" -#include "common/internal/reference_count.h" -#include "common/reference_count.h" -#include "internal/exceptions.h" #include "internal/to_address.h" // IWYU pragma: keep #include "google/protobuf/arena.h" @@ -57,1252 +48,10 @@ enum class MemoryManagement { std::ostream& operator<<(std::ostream& out, MemoryManagement memory_management); -class ABSL_ATTRIBUTE_TRIVIAL_ABI [[nodiscard]] Owner; -class Borrower; -template -class ABSL_ATTRIBUTE_TRIVIAL_ABI [[nodiscard]] Unique; -template -class ABSL_ATTRIBUTE_TRIVIAL_ABI [[nodiscard]] Owned; -template -class Borrowed; -template -struct Ownable; -template -struct Borrowable; - class MemoryManager; class ReferenceCountingMemoryManager; class PoolingMemoryManager; -namespace common_internal { -template -inline constexpr bool kNotMessageLiteAndNotData = - std::conjunction_v>, - std::negation>>; -template -inline constexpr bool kIsPointerConvertible = std::is_convertible_v; -template -inline constexpr bool kNotSameAndIsPointerConvertible = - std::conjunction_v>, - std::bool_constant>>; - -// Clears the contents of `owner`, and returns the reference count if in use. -const ReferenceCount* absl_nullable OwnerRelease(Owner owner) noexcept; -const ReferenceCount* absl_nullable BorrowerRelease(Borrower borrower) noexcept; -template -Owned WrapEternal(const T* value); - -// Pointer tag used by `cel::Unique` to indicate that the destructor needs to be -// registered with the arena, but it has not been done yet. Must be done when -// releasing. -inline constexpr uintptr_t kUniqueArenaUnownedBit = uintptr_t{1} << 0; -inline constexpr uintptr_t kUniqueArenaBits = kUniqueArenaUnownedBit; -inline constexpr uintptr_t kUniqueArenaPointerMask = ~kUniqueArenaBits; -} // namespace common_internal - -template -Owned AllocateShared(Allocator<> allocator, Args&&... args); - -template -Owned WrapShared(T* object, Allocator<> allocator); - -// `Owner` represents a reference to some co-owned data, of which this owner is -// one of the co-owners. When using reference counting, `Owner` performs -// increment/decrement where appropriate similar to `std::shared_ptr`. -// `Borrower` is similar to `Owner`, except that it is always trivially -// copyable/destructible. In that sense, `Borrower` is similar to -// `std::reference_wrapper`. -class ABSL_ATTRIBUTE_TRIVIAL_ABI [[nodiscard]] Owner final { - private: - static constexpr uintptr_t kNone = common_internal::kMetadataOwnerNone; - static constexpr uintptr_t kReferenceCountBit = - common_internal::kMetadataOwnerReferenceCountBit; - static constexpr uintptr_t kArenaBit = - common_internal::kMetadataOwnerArenaBit; - static constexpr uintptr_t kBits = common_internal::kMetadataOwnerBits; - static constexpr uintptr_t kPointerMask = - common_internal::kMetadataOwnerPointerMask; - - public: - static Owner None() noexcept { return Owner(); } - - static Owner Allocator(Allocator<> allocator) noexcept { - auto* arena = allocator.arena(); - return arena != nullptr ? Arena(arena) : None(); - } - - static Owner Arena(google::protobuf::Arena* absl_nonnull arena - ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept { - ABSL_DCHECK(arena != nullptr); - return Owner(reinterpret_cast(arena) | kArenaBit); - } - - static Owner Arena(std::nullptr_t) = delete; - - static Owner ReferenceCount(const ReferenceCount* absl_nonnull reference_count - ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept { - ABSL_DCHECK(reference_count != nullptr); - common_internal::StrongRef(*reference_count); - return Owner(reinterpret_cast(reference_count) | - kReferenceCountBit); - } - - static Owner ReferenceCount(std::nullptr_t) = delete; - - Owner() = default; - - Owner(const Owner& other) noexcept : Owner(CopyFrom(other.ptr_)) {} - - Owner(Owner&& other) noexcept : Owner(MoveFrom(other.ptr_)) {} - - template - // NOLINTNEXTLINE(google-explicit-constructor) - Owner(const Owned& owned) noexcept; - - template - // NOLINTNEXTLINE(google-explicit-constructor) - Owner(Owned&& owned) noexcept; - - explicit Owner(Borrower borrower) noexcept; - - template - explicit Owner(Borrowed borrowed) noexcept; - - ~Owner() { Destroy(ptr_); } - - Owner& operator=(const Owner& other) noexcept { - if (ptr_ != other.ptr_) { - Destroy(ptr_); - ptr_ = CopyFrom(other.ptr_); - } - return *this; - } - - Owner& operator=(Owner&& other) noexcept { - if (ABSL_PREDICT_TRUE(this != &other)) { - Destroy(ptr_); - ptr_ = MoveFrom(other.ptr_); - } - return *this; - } - - template - // NOLINTNEXTLINE(google-explicit-constructor) - Owner& operator=(const Owned& owned) noexcept; - - template - // NOLINTNEXTLINE(google-explicit-constructor) - Owner& operator=(Owned&& owned) noexcept; - - explicit operator bool() const noexcept { return !IsNone(ptr_); } - - google::protobuf::Arena* absl_nullable arena() const noexcept { - return (ptr_ & Owner::kBits) == Owner::kArenaBit - ? reinterpret_cast(ptr_ & Owner::kPointerMask) - : nullptr; - } - - void reset() noexcept { - Destroy(ptr_); - ptr_ = 0; - } - - // Tests whether two owners have ownership over the same data, that is they - // are co-owners. - friend bool operator==(const Owner& lhs, const Owner& rhs) noexcept { - // A reference count and arena can never occupy the same memory address, so - // we can compare for equality without masking off the bits. - return lhs.ptr_ == rhs.ptr_; - } - - private: - template - friend class Unique; - friend class Borrower; - template - friend Owned AllocateShared(cel::Allocator<> allocator, Args&&... args); - template - friend Owned WrapShared(T* object, cel::Allocator<> allocator); - template - friend struct Ownable; - friend const common_internal::ReferenceCount* absl_nullable - common_internal::OwnerRelease(Owner owner) noexcept; - friend const common_internal::ReferenceCount* absl_nullable - common_internal::BorrowerRelease(Borrower borrower) noexcept; - friend struct ArenaTraits; - - constexpr explicit Owner(uintptr_t ptr) noexcept : ptr_(ptr) {} - - static constexpr bool IsNone(uintptr_t ptr) noexcept { return ptr == kNone; } - - static constexpr bool IsArena(uintptr_t ptr) noexcept { - return (ptr & kArenaBit) != kNone; - } - - static constexpr bool IsReferenceCount(uintptr_t ptr) noexcept { - return (ptr & kReferenceCountBit) != kNone; - } - - ABSL_ATTRIBUTE_RETURNS_NONNULL - static google::protobuf::Arena* absl_nonnull AsArena(uintptr_t ptr) noexcept { - ABSL_ASSERT(IsArena(ptr)); - return reinterpret_cast(ptr & kPointerMask); - } - - ABSL_ATTRIBUTE_RETURNS_NONNULL - static const common_internal::ReferenceCount* absl_nonnull AsReferenceCount( - uintptr_t ptr) noexcept { - ABSL_ASSERT(IsReferenceCount(ptr)); - return reinterpret_cast( - ptr & kPointerMask); - } - - static uintptr_t CopyFrom(uintptr_t other) noexcept { return Own(other); } - - static uintptr_t MoveFrom(uintptr_t& other) noexcept { - return std::exchange(other, kNone); - } - - static void Destroy(uintptr_t ptr) noexcept { Unown(ptr); } - - static uintptr_t Own(uintptr_t ptr) noexcept { - if (IsReferenceCount(ptr)) { - const auto* refcount = Owner::AsReferenceCount(ptr); - ABSL_ASSUME(refcount != nullptr); - common_internal::StrongRef(refcount); - } - return ptr; - } - - static void Unown(uintptr_t ptr) noexcept { - if (IsReferenceCount(ptr)) { - const auto* reference_count = AsReferenceCount(ptr); - ABSL_ASSUME(reference_count != nullptr); - common_internal::StrongUnref(reference_count); - } - } - - uintptr_t ptr_ = kNone; -}; - -inline bool operator!=(const Owner& lhs, const Owner& rhs) noexcept { - return !operator==(lhs, rhs); -} - -namespace common_internal { - -inline const ReferenceCount* absl_nullable OwnerRelease(Owner owner) noexcept { - uintptr_t ptr = std::exchange(owner.ptr_, kMetadataOwnerNone); - if (Owner::IsReferenceCount(ptr)) { - return Owner::AsReferenceCount(ptr); - } - return nullptr; -} - -} // namespace common_internal - -template <> -struct ArenaTraits { - static bool trivially_destructible(const Owner& owner) { - return !Owner::IsReferenceCount(owner.ptr_); - } -}; - -// `Borrower` represents a reference to some borrowed data, where the data has -// at least one owner. When using reference counting, `Borrower` does not -// participate in incrementing/decrementing the reference count. Thus `Borrower` -// will not keep the underlying data alive. -class Borrower final { - public: - static Borrower None() noexcept { return Borrower(); } - - static Borrower Allocator(Allocator<> allocator) noexcept { - auto* arena = allocator.arena(); - return arena != nullptr ? Arena(arena) : None(); - } - - static Borrower Arena(google::protobuf::Arena* absl_nonnull arena - ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept { - ABSL_DCHECK(arena != nullptr); - return Borrower(reinterpret_cast(arena) | Owner::kArenaBit); - } - - static Borrower Arena(std::nullptr_t) = delete; - - static Borrower ReferenceCount( - const ReferenceCount* absl_nonnull reference_count - ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept { - ABSL_DCHECK(reference_count != nullptr); - return Borrower(reinterpret_cast(reference_count) | - Owner::kReferenceCountBit); - } - - static Borrower ReferenceCount(std::nullptr_t) = delete; - - Borrower() = default; - Borrower(const Borrower&) = default; - Borrower(Borrower&&) = default; - Borrower& operator=(const Borrower&) = default; - Borrower& operator=(Borrower&&) = default; - - template - // NOLINTNEXTLINE(google-explicit-constructor) - Borrower(const Owned& owned ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept; - - template - // NOLINTNEXTLINE(google-explicit-constructor) - Borrower(Borrowed borrowed) noexcept; - - // NOLINTNEXTLINE(google-explicit-constructor) - Borrower(const Owner& owner ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept - : ptr_(owner.ptr_) {} - - // NOLINTNEXTLINE(google-explicit-constructor) - Borrower& operator=( - const Owner& owner ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept { - ptr_ = owner.ptr_; - return *this; - } - - Borrower& operator=(Owner&&) = delete; - - template - Borrower& operator=( - const Owned& owned ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept; - - template - Borrower& operator=(Owned&&) = delete; - - template - // NOLINTNEXTLINE(google-explicit-constructor) - Borrower& operator=(Borrowed borrowed) noexcept; - - explicit operator bool() const noexcept { return !Owner::IsNone(ptr_); } - - google::protobuf::Arena* absl_nullable arena() const noexcept { - return (ptr_ & Owner::kBits) == Owner::kArenaBit - ? reinterpret_cast(ptr_ & Owner::kPointerMask) - : nullptr; - } - - void reset() noexcept { ptr_ = 0; } - - // Tests whether two borrowers are borrowing the same data. - friend bool operator==(Borrower lhs, Borrower rhs) noexcept { - // A reference count and arena can never occupy the same memory address, so - // we can compare for equality without masking off the bits. - return lhs.ptr_ == rhs.ptr_; - } - - private: - friend class Owner; - template - friend struct Borrowable; - friend const common_internal::ReferenceCount* absl_nullable - common_internal::BorrowerRelease(Borrower borrower) noexcept; - - constexpr explicit Borrower(uintptr_t ptr) noexcept : ptr_(ptr) {} - - uintptr_t ptr_ = Owner::kNone; -}; - -inline bool operator!=(Borrower lhs, Borrower rhs) noexcept { - return !operator==(lhs, rhs); -} - -inline bool operator==(Borrower lhs, const Owner& rhs) noexcept { - return operator==(lhs, Borrower(rhs)); -} - -inline bool operator==(const Owner& lhs, Borrower rhs) noexcept { - return operator==(Borrower(lhs), rhs); -} - -inline bool operator!=(Borrower lhs, const Owner& rhs) noexcept { - return !operator==(lhs, rhs); -} - -inline bool operator!=(const Owner& lhs, Borrower rhs) noexcept { - return !operator==(lhs, rhs); -} - -inline Owner::Owner(Borrower borrower) noexcept - : ptr_(Owner::Own(borrower.ptr_)) {} - -namespace common_internal { - -inline const ReferenceCount* absl_nullable BorrowerRelease( - Borrower borrower) noexcept { - uintptr_t ptr = borrower.ptr_; - if (Owner::IsReferenceCount(ptr)) { - return Owner::AsReferenceCount(ptr); - } - return nullptr; -} - -} // namespace common_internal - -template -Unique AllocateUnique(Allocator<> allocator, Args&&... args); - -// Wrap an already created `T` in `Unique`. Requires that `T` is not const, -// otherwise `GetArena()` may return slightly unexpected results depending on if -// it is the default value. -template -std::enable_if_t, Unique> WrapUnique(T* object); - -template -Unique WrapUnique(T* object, Allocator<> allocator); - -// `Unique` points to an object which was allocated using `Allocator<>` or -// `Allocator`. It has ownership over the object, and will perform any -// destruction and deallocation required. `Unique` must not outlive the -// underlying arena, if any. Unlike `Owned` and `Borrowed`, `Unique` supports -// arena incompatible objects. It is very similar to `std::unique_ptr` when -// using a custom deleter. -// -// IMPLEMENTATION NOTES: -// When utilizing arenas, we optionally perform a risky optimization via -// `AllocateUnique`. We do not use `Arena::Create`, instead we directly allocate -// the bytes and construct it in place ourselves. This avoids registering the -// destructor when required. Instead we register the destructor ourselves, if -// required, during `Unique::release`. This allows us to avoid deferring -// destruction of the object until the arena is destroyed, avoiding the cost -// involved in doing so. -template -class ABSL_ATTRIBUTE_TRIVIAL_ABI [[nodiscard]] Unique final { - public: - using element_type = T; - - static_assert(!std::is_array_v, "T must not be an array"); - static_assert(!std::is_reference_v, "T must not be a reference"); - static_assert(!std::is_volatile_v, "T must not be volatile qualified"); - - Unique() = default; - Unique(const Unique&) = delete; - Unique& operator=(const Unique&) = delete; - - explicit Unique(T* ptr) noexcept - : Unique(ptr, common_internal::GetArena(ptr)) {} - - // NOLINTNEXTLINE(google-explicit-constructor) - Unique(std::nullptr_t) noexcept : Unique() {} - - Unique(Unique&& other) noexcept : Unique(other.ptr_, other.arena_) { - other.ptr_ = nullptr; - } - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Unique(Unique&& other) noexcept : Unique(other.ptr_, other.arena_) { - other.ptr_ = nullptr; - } - - ~Unique() { Delete(); } - - Unique& operator=(Unique&& other) noexcept { - if (ABSL_PREDICT_TRUE(this != &other)) { - Delete(); - ptr_ = other.ptr_; - arena_ = other.arena_; - other.ptr_ = nullptr; - } - return *this; - } - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Unique& operator=(U* other) noexcept { - reset(other); - return *this; - } - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Unique& operator=(Unique&& other) noexcept { - Delete(); - ptr_ = other.ptr_; - arena_ = other.arena_; - other.ptr_ = nullptr; - return *this; - } - - // NOLINTNEXTLINE(google-explicit-constructor) - Unique& operator=(std::nullptr_t) noexcept { - reset(); - return *this; - } - - T& operator*() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND { - ABSL_DCHECK(static_cast(*this)); - return *get(); - } - - T* absl_nonnull operator->() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND { - ABSL_DCHECK(static_cast(*this)); - return get(); - } - - // Relinquishes ownership of `T*`, returning it. If `T` was allocated and - // constructed using an arena, no further action is required. If `T` was - // allocated and constructed without an arena, the caller must eventually call - // `delete`. - ABSL_MUST_USE_RESULT T* release() noexcept { - PreRelease(); - return std::exchange(ptr_, nullptr); - } - - void reset() noexcept { reset(nullptr); } - - void reset(T* ptr) noexcept { - Delete(); - ptr_ = ptr; - arena_ = reinterpret_cast(common_internal::GetArena(ptr)); - } - - void reset(std::nullptr_t) noexcept { - Delete(); - ptr_ = nullptr; - arena_ = 0; - } - - explicit operator bool() const noexcept { return get() != nullptr; } - - google::protobuf::Arena* absl_nullable arena() const noexcept { - return reinterpret_cast( - arena_ & common_internal::kUniqueArenaPointerMask); - } - - friend void swap(Unique& lhs, Unique& rhs) noexcept { - using std::swap; - swap(lhs.ptr_, rhs.ptr_); - swap(lhs.arena_, rhs.arena_); - } - - private: - template - friend class Unique; - template - friend class Owned; - template - friend Unique AllocateUnique(Allocator<> allocator, Args&&... args); - template - friend Unique WrapUnique(U* object, Allocator<> allocator); - friend class ReferenceCountingMemoryManager; - friend class PoolingMemoryManager; - friend struct std::pointer_traits>; - friend struct ArenaTraits>; - - static constexpr bool kNeedsArenaDestructor = - !std::is_trivially_destructible_v && - !google::protobuf::Arena::is_destructor_skippable::value && - !std::is_base_of_v; - - Unique(T* ptr, uintptr_t arena) noexcept : ptr_(ptr), arena_(arena) {} - - Unique(T* ptr, google::protobuf::Arena* arena, bool unowned = false) noexcept - : Unique(ptr, - reinterpret_cast(arena) | - (unowned ? common_internal::kUniqueArenaUnownedBit : 0)) { - ABSL_ASSERT(!unowned || (unowned && arena != nullptr)); - } - - Unique(google::protobuf::Arena* arena, T* ptr, bool unowned = false) noexcept - : Unique(ptr, arena, unowned) {} - - T* get() const noexcept { return ptr_; } - - void Delete() const noexcept { - if (static_cast(*this)) { - if (arena_ != 0) { - if ((arena_ & common_internal::kUniqueArenaBits) == - common_internal::kUniqueArenaUnownedBit) { - // We never registered the destructor, call it if necessary. - if constexpr (kNeedsArenaDestructor) { - std::destroy_at(ptr_); - } - } - } else { - delete ptr_; - } - } - } - - void PreRelease() noexcept { - if constexpr (kNeedsArenaDestructor) { - if (static_cast(*this) && - (arena_ & common_internal::kUniqueArenaBits) == - common_internal::kUniqueArenaUnownedBit) { - // We never registered the destructor, call it if necessary. - arena()->OwnDestructor(const_cast*>(ptr_)); - arena_ &= common_internal::kUniqueArenaPointerMask; - } - } - } - - void Release(T** ptr, Owner* owner) noexcept { - if (ptr_ == nullptr) { - *ptr = nullptr; - return; - } - PreRelease(); - *ptr = std::exchange(ptr_, nullptr); - if (arena_ == 0) { - owner->ptr_ = reinterpret_cast( - common_internal::MakeDeletingReferenceCount(*ptr)) | - common_internal::kMetadataOwnerReferenceCountBit; - } else { - owner->ptr_ = reinterpret_cast(arena()) | - common_internal::kMetadataOwnerArenaBit; - } - } - - T* ptr_ = nullptr; - // Potentially tagged pointer to `google::protobuf::Arena`. The tag is used to determine - // whether we still need to register the destructor with the `google::protobuf::Arena`. - uintptr_t arena_ = 0; -}; - -template -Unique(T*) -> Unique; - -template -Unique AllocateUnique(Allocator<> allocator, Args&&... args) { - using U = std::remove_cv_t; - static_assert(!std::is_reference_v, "T must not be a reference"); - static_assert(!std::is_array_v, "T must not be an array"); - - U* object; - google::protobuf::Arena* absl_nullable arena = allocator.arena(); - bool unowned; - if constexpr (google::protobuf::Arena::is_arena_constructable::value) { - object = google::protobuf::Arena::Create(arena, std::forward(args)...); - // For arena-compatible proto types, let the Arena::Create handle - // registering the destructor call. - // Otherwise, Unique retains a pointer to the owning arena so it may - // conditionally register T::~T depending on usage. - unowned = false; - } else { - void* p = allocator.allocate_bytes(sizeof(U), alignof(U)); - CEL_INTERNAL_TRY { - if constexpr (ArenaTraits<>::constructible()) { - object = ::new (p) U(arena, std::forward(args)...); - } else { - object = ::new (p) U(std::forward(args)...); - } - } - CEL_INTERNAL_CATCH_ANY { - allocator.deallocate_bytes(p, sizeof(U), alignof(U)); - CEL_INTERNAL_RETHROW; - } - unowned = - arena != nullptr && !ArenaTraits<>::trivially_destructible(*object); - } - return Unique(object, arena, unowned); -} - -template -std::enable_if_t, Unique> WrapUnique(T* object) { - return Unique(object); -} - -template -Unique WrapUnique(T* object, Allocator<> allocator) { - return Unique(object, allocator.arena()); -} - -template -inline bool operator==(const Unique& lhs, std::nullptr_t) { - return !static_cast(lhs); -} - -template -inline bool operator==(std::nullptr_t, const Unique& rhs) { - return !static_cast(rhs); -} - -template -inline bool operator!=(const Unique& lhs, std::nullptr_t) { - return static_cast(lhs); -} - -template -inline bool operator!=(std::nullptr_t, const Unique& rhs) { - return static_cast(rhs); -} - -} // namespace cel - -namespace std { - -template -struct pointer_traits> { - using pointer = cel::Unique; - using element_type = typename cel::Unique::element_type; - using difference_type = ptrdiff_t; - - template - using rebind = cel::Unique; - - static element_type* to_address(const pointer& p) noexcept { return p.ptr_; } -}; - -} // namespace std - -namespace cel { - -template -struct ArenaTraits> { - static bool trivially_destructible(const Unique& unique) { - return unique.arena_ != 0 && - (unique.arena_ & common_internal::kUniqueArenaBits) == 0; - } -}; - -// `Owned` points to an object which was allocated using `Allocator<>` or -// `Allocator`. It has co-ownership over the object. `T` must meet the named -// requirement `ArenaConstructable`. -template -class ABSL_ATTRIBUTE_TRIVIAL_ABI [[nodiscard]] Owned final { - public: - using element_type = T; - - static_assert(!std::is_array_v, "T must not be an array"); - static_assert(!std::is_reference_v, "T must not be a reference"); - static_assert(!std::is_volatile_v, "T must not be volatile qualified"); - static_assert(!std::is_void_v, "T must not be void"); - - Owned() = default; - Owned(const Owned&) = default; - Owned& operator=(const Owned&) = default; - - Owned(Owned&& other) noexcept - : Owned(std::exchange(other.value_, nullptr), std::move(other.owner_)) {} - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Owned(const Owned& other) noexcept : Owned(other.value_, other.owner_) {} - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Owned(Owned&& other) noexcept - : Owned(std::exchange(other.value_, nullptr), std::move(other.owner_)) {} - - template >> - explicit Owned(Borrowed other) noexcept; - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Owned(Unique&& other) : Owned() { - other.Release(&value_, &owner_); - } - - Owned(Owner owner, T* value ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept - : Owned(value, std::move(owner)) {} - - // NOLINTNEXTLINE(google-explicit-constructor) - Owned(std::nullptr_t) noexcept : Owned() {} - - Owned& operator=(Owned&& other) noexcept { - if (ABSL_PREDICT_TRUE(this != &other)) { - value_ = std::exchange(other.value_, nullptr); - owner_ = std::move(other.owner_); - } - return *this; - } - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Owned& operator=(const Owned& other) noexcept { - value_ = other.value_; - owner_ = other.owner_; - return *this; - } - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Owned& operator=(Owned&& other) noexcept { - value_ = std::exchange(other.value_, nullptr); - owner_ = std::move(other.owner_); - return *this; - } - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Owned& operator=(Borrowed other) noexcept; - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Owned& operator=(Unique&& other) { - owner_.reset(); - other.Release(&value_, &owner_); - return *this; - } - - // NOLINTNEXTLINE(google-explicit-constructor) - Owned& operator=(std::nullptr_t) noexcept { - reset(); - return *this; - } - - T& operator*() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND { - ABSL_DCHECK(static_cast(*this)); - return *get(); - } - - T* absl_nonnull operator->() const noexcept ABSL_ATTRIBUTE_LIFETIME_BOUND { - ABSL_DCHECK(static_cast(*this)); - return get(); - } - - void reset() noexcept { - value_ = nullptr; - owner_.reset(); - } - - google::protobuf::Arena* absl_nullable arena() const noexcept { return owner_.arena(); } - - explicit operator bool() const noexcept { return get() != nullptr; } - - friend void swap(Owned& lhs, Owned& rhs) noexcept { - using std::swap; - swap(lhs.value_, rhs.value_); - swap(lhs.owner_, rhs.owner_); - } - - private: - friend class Owner; - friend class Borrower; - template - friend class Owned; - template - friend class Borrowed; - template - friend struct Ownable; - template - friend Owned AllocateShared(Allocator<> allocator, Args&&... args); - template - friend Owned WrapShared(U* object, Allocator<> allocator); - template - friend Owned common_internal::WrapEternal(const U* value); - friend struct std::pointer_traits>; - friend struct ArenaTraits>; - - Owned(T* value, Owner owner) noexcept - : value_(value), owner_(std::move(owner)) {} - - T* get() const noexcept { return value_; } - - T* value_ = nullptr; - Owner owner_; -}; - -template -Owned(T*) -> Owned; -template -Owned(Unique) -> Owned; -template -Owned(Owner, T*) -> Owned; -template -Owned(Borrowed) -> Owned; - -} // namespace cel - -namespace std { - -template -struct pointer_traits> { - using pointer = cel::Owned; - using element_type = typename cel::Owned::element_type; - using difference_type = ptrdiff_t; - - template - using rebind = cel::Owned; - - static element_type* to_address(const pointer& p) noexcept { - return p.value_; - } -}; - -} // namespace std - -namespace cel { - -template -struct ArenaTraits> { - static bool trivially_destructible(const Owned& owned) { - return ArenaTraits<>::trivially_destructible(owned.owner_); - } -}; - -template -Owner::Owner(const Owned& owned) noexcept : Owner(owned.owner_) {} - -template -Owner::Owner(Owned&& owned) noexcept : Owner(std::move(owned.owner_)) { - owned.value_ = nullptr; -} - -template -Owner& Owner::operator=(const Owned& owned) noexcept { - *this = owned.owner_; - return *this; -} - -template -Owner& Owner::operator=(Owned&& owned) noexcept { - *this = std::move(owned.owner_); - owned.value_ = nullptr; - return *this; -} - -template -bool operator==(const Owned& lhs, std::nullptr_t) noexcept { - return !static_cast(lhs); -} - -template -bool operator==(std::nullptr_t, const Owned& rhs) noexcept { - return rhs == nullptr; -} - -template -bool operator!=(const Owned& lhs, std::nullptr_t) noexcept { - return !operator==(lhs, nullptr); -} - -template -bool operator!=(std::nullptr_t, const Owned& rhs) noexcept { - return !operator==(nullptr, rhs); -} - -template -Owned AllocateShared(Allocator<> allocator, Args&&... args) { - using U = std::remove_cv_t; - static_assert(!std::is_reference_v, "T must not be a reference"); - static_assert(!std::is_array_v, "T must not be an array"); - - U* object; - Owner owner; - if (google::protobuf::Arena* absl_nullable arena = allocator.arena(); - arena != nullptr) { - object = ArenaAllocator(arena).template new_object( - std::forward(args)...); - owner.ptr_ = reinterpret_cast(arena) | - common_internal::kMetadataOwnerArenaBit; - } else { - const common_internal::ReferenceCount* refcount; - std::tie(object, refcount) = common_internal::MakeEmplacedReferenceCount( - std::forward(args)...); - owner.ptr_ = reinterpret_cast(refcount) | - common_internal::kMetadataOwnerReferenceCountBit; - } - return Owned(object, std::move(owner)); -} - -template -Owned WrapShared(T* object, Allocator<> allocator) { - Owner owner; - if (object == nullptr) { - } else if (allocator.arena() != nullptr) { - owner.ptr_ = reinterpret_cast( - static_cast(allocator.arena())) | - common_internal::kMetadataOwnerArenaBit; - } else { - owner.ptr_ = reinterpret_cast( - common_internal::MakeDeletingReferenceCount(object)) | - common_internal::kMetadataOwnerReferenceCountBit; - } - return Owned(object, std::move(owner)); -} - -template -std::enable_if_t, Owned> WrapShared(T* object) { - return WrapShared(object, object->GetArena()); -} - -namespace common_internal { - -template -Owned WrapEternal(const T* value) { - return Owned(value, Owner::None()); -} - -} // namespace common_internal - -// `Borrowed` points to an object which was allocated using `Allocator<>` or -// `Allocator`. It has no ownership over the object, and is only valid so -// long as one or more owners of the object exist. `T` must meet the named -// requirement `ArenaConstructable`. -template -class Borrowed final { - public: - using element_type = T; - - static_assert(!std::is_array_v, "T must not be an array"); - static_assert(!std::is_reference_v, "T must not be a reference"); - static_assert(!std::is_volatile_v, "T must not be volatile qualified"); - static_assert(!std::is_void_v, "T must not be void"); - - Borrowed() = default; - Borrowed(const Borrowed&) = default; - Borrowed(Borrowed&&) = default; - Borrowed& operator=(const Borrowed&) = default; - Borrowed& operator=(Borrowed&&) = default; - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Borrowed(const Borrowed& other) noexcept - : Borrowed(other.value_, other.borrower_) {} - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Borrowed(Borrowed&& other) noexcept - : Borrowed(other.value_, other.borrower_) {} - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Borrowed(const Owned& other ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept - : Borrowed(other.value_, other.owner_) {} - - Borrowed(Borrower borrower, T* ptr) noexcept : Borrowed(ptr, borrower) {} - - // NOLINTNEXTLINE(google-explicit-constructor) - Borrowed(std::nullptr_t) noexcept : Borrowed() {} - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Borrowed& operator=(const Borrowed& other) noexcept { - value_ = other.value_; - borrower_ = other.borrower_; - return *this; - } - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Borrowed& operator=(Borrowed&& other) noexcept { - value_ = other.value_; - borrower_ = other.borrower_; - return *this; - } - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Borrowed& operator=( - const Owned& other ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept { - value_ = other.value_; - borrower_ = other.borrower_; - return *this; - } - - template >> - // NOLINTNEXTLINE(google-explicit-constructor) - Borrowed& operator=(Owned&&) = delete; - - // NOLINTNEXTLINE(google-explicit-constructor) - Borrowed& operator=(std::nullptr_t) noexcept { - reset(); - return *this; - } - - T& operator*() const noexcept { - ABSL_DCHECK(static_cast(*this)); - return *get(); - } - - T* absl_nonnull operator->() const noexcept { - ABSL_DCHECK(static_cast(*this)); - return get(); - } - - void reset() noexcept { - value_ = nullptr; - borrower_.reset(); - } - - google::protobuf::Arena* absl_nullable arena() const noexcept { - return borrower_.arena(); - } - - explicit operator bool() const noexcept { return get() != nullptr; } - - private: - friend class Owner; - friend class Borrower; - template - friend class Owned; - template - friend class Borrowed; - template - friend struct Borrowable; - friend struct std::pointer_traits>; - - constexpr Borrowed(T* value, Borrower borrower) noexcept - : value_(value), borrower_(borrower) {} - - T* get() const noexcept { return value_; } - - T* value_ = nullptr; - Borrower borrower_; -}; - -template -Borrowed(T*) -> Borrowed; -template -Borrowed(Borrower, T*) -> Borrowed; -template -Borrowed(Owned) -> Borrowed; - -} // namespace cel - -namespace std { - -template -struct pointer_traits> { - using pointer = cel::Borrowed; - using element_type = typename cel::Borrowed::element_type; - using difference_type = ptrdiff_t; - - template - using rebind = cel::Borrowed; - - static element_type* to_address(pointer p) noexcept { return p.value_; } -}; - -} // namespace std - -namespace cel { - -template -Owner::Owner(Borrowed borrowed) noexcept : Owner(borrowed.borrower_) {} - -template -Borrower::Borrower(const Owned& owned ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept - : Borrower(owned.owner_) {} - -template -Borrower::Borrower(Borrowed borrowed) noexcept - : Borrower(borrowed.borrower_) {} - -template -Borrower& Borrower::operator=( - const Owned& owned ABSL_ATTRIBUTE_LIFETIME_BOUND) noexcept { - *this = owned.owner_; - return *this; -} - -template -Borrower& Borrower::operator=(Borrowed borrowed) noexcept { - *this = borrowed.borrower_; - return *this; -} - -template -bool operator==(Borrowed lhs, std::nullptr_t) noexcept { - return !static_cast(lhs); -} - -template -bool operator==(std::nullptr_t, Borrowed rhs) noexcept { - return rhs == nullptr; -} - -template -bool operator!=(Borrowed lhs, std::nullptr_t) noexcept { - return !operator==(lhs, nullptr); -} - -template -bool operator!=(std::nullptr_t, Borrowed rhs) noexcept { - return !operator==(nullptr, rhs); -} - -template -template -Owned::Owned(Borrowed other) noexcept - : Owned(other.value_, Owner(other.borrower_)) {} - -template -template -Owned& Owned::operator=(Borrowed other) noexcept { - value_ = other.value_; - owner_ = Owner(other.borrower_); - return *this; -} - -// `Ownable` is a mixin for enabling the ability to get `Owned` that refer to -// this. -template -struct Ownable { - protected: - Owned Own() const noexcept { - static_assert(std::is_base_of_v, "T must be derived from Data"); - const T* const that = static_cast(this); - return Owned( - Owner(Owner::Own(static_cast(that)->owner_)), that); - } - - Owned Own() noexcept { - static_assert(std::is_base_of_v, "T must be derived from Data"); - T* const that = static_cast(this); - return Owned(Owner(Owner::Own(static_cast(that)->owner_)), that); - } - - ABSL_DEPRECATED("Use Own") - Owned shared_from_this() const noexcept { return Own(); } - - ABSL_DEPRECATED("Use Own") - Owned shared_from_this() noexcept { return Own(); } -}; - -// `Borrowable` is a mixin for enabling the ability to get `Borrowed` that -// refer to this. -template -struct Borrowable { - protected: - Borrowed Borrow() const noexcept { - static_assert(std::is_base_of_v, "T must be derived from Data"); - const T* const that = static_cast(this); - return Borrowed(Borrower(static_cast(that)->owner_), - that); - } - - Borrowed Borrow() noexcept { - static_assert(std::is_base_of_v, "T must be derived from Data"); - T* const that = static_cast(this); - return Borrowed(Borrower(static_cast(that)->owner_), that); - } -}; - // `ReferenceCountingMemoryManager` is a `MemoryManager` which employs automatic // memory management through reference counting. class ReferenceCountingMemoryManager final { diff --git a/common/memory_test.cc b/common/memory_test.cc deleted file mode 100644 index 7f3e7a82a..000000000 --- a/common/memory_test.cc +++ /dev/null @@ -1,466 +0,0 @@ -// Copyright 2023 Google LLC -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// https://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -// This header contains primitives for reference counting, roughly equivalent to -// the primitives used to implement `std::shared_ptr`. These primitives should -// not be used directly in most cases, instead `cel::ManagedMemory` should be -// used instead. - -#include "common/memory.h" - -#include - -#include "google/protobuf/struct.pb.h" -#include "absl/base/nullability.h" -#include "common/allocator.h" -#include "common/data.h" -#include "common/internal/reference_count.h" -#include "internal/testing.h" -#include "google/protobuf/arena.h" - -#ifdef ABSL_HAVE_EXCEPTIONS -#include -#endif - -namespace cel { -namespace { - -using ::testing::IsFalse; -using ::testing::IsNull; -using ::testing::IsTrue; -using ::testing::TestParamInfo; -using ::testing::TestWithParam; - -TEST(Owner, None) { - EXPECT_THAT(Owner::None(), IsFalse()); - EXPECT_THAT(Owner::None().arena(), IsNull()); -} - -TEST(Owner, Allocator) { - google::protobuf::Arena arena; - EXPECT_THAT(Owner::Allocator(NewDeleteAllocator<>{}), IsFalse()); - EXPECT_THAT(Owner::Allocator(ArenaAllocator<>{&arena}), IsTrue()); -} - -TEST(Owner, Arena) { - google::protobuf::Arena arena; - EXPECT_THAT(Owner::Arena(&arena), IsTrue()); - EXPECT_EQ(Owner::Arena(&arena).arena(), &arena); -} - -TEST(Owner, ReferenceCount) { - auto* refcount = new common_internal::ReferenceCounted(); - EXPECT_THAT(Owner::ReferenceCount(refcount), IsTrue()); - EXPECT_THAT(Owner::ReferenceCount(refcount).arena(), IsNull()); - common_internal::StrongUnref(refcount); -} - -TEST(Owner, Equality) { - google::protobuf::Arena arena1; - google::protobuf::Arena arena2; - EXPECT_EQ(Owner::None(), Owner::None()); - EXPECT_EQ(Owner::Allocator(NewDeleteAllocator<>{}), Owner::None()); - EXPECT_EQ(Owner::Arena(&arena1), Owner::Arena(&arena1)); - EXPECT_NE(Owner::Arena(&arena1), Owner::None()); - EXPECT_NE(Owner::None(), Owner::Arena(&arena1)); - EXPECT_NE(Owner::Arena(&arena1), Owner::Arena(&arena2)); - EXPECT_EQ(Owner::Allocator(ArenaAllocator<>{&arena1}), Owner::Arena(&arena1)); -} - -TEST(Borrower, None) { - EXPECT_THAT(Borrower::None(), IsFalse()); - EXPECT_THAT(Borrower::None().arena(), IsNull()); -} - -TEST(Borrower, Allocator) { - google::protobuf::Arena arena; - EXPECT_THAT(Borrower::Allocator(NewDeleteAllocator<>{}), IsFalse()); - EXPECT_THAT(Borrower::Allocator(ArenaAllocator<>{&arena}), IsTrue()); -} - -TEST(Borrower, Arena) { - google::protobuf::Arena arena; - EXPECT_THAT(Borrower::Arena(&arena), IsTrue()); - EXPECT_EQ(Borrower::Arena(&arena).arena(), &arena); -} - -TEST(Borrower, ReferenceCount) { - auto* refcount = new common_internal::ReferenceCounted(); - EXPECT_THAT(Borrower::ReferenceCount(refcount), IsTrue()); - EXPECT_THAT(Borrower::ReferenceCount(refcount).arena(), IsNull()); - common_internal::StrongUnref(refcount); -} - -TEST(Borrower, Equality) { - google::protobuf::Arena arena1; - google::protobuf::Arena arena2; - EXPECT_EQ(Borrower::None(), Borrower::None()); - EXPECT_EQ(Borrower::Allocator(NewDeleteAllocator<>{}), Borrower::None()); - EXPECT_EQ(Borrower::Arena(&arena1), Borrower::Arena(&arena1)); - EXPECT_NE(Borrower::Arena(&arena1), Borrower::None()); - EXPECT_NE(Borrower::None(), Borrower::Arena(&arena1)); - EXPECT_NE(Borrower::Arena(&arena1), Borrower::Arena(&arena2)); - EXPECT_EQ(Borrower::Allocator(ArenaAllocator<>{&arena1}), - Borrower::Arena(&arena1)); -} - -TEST(OwnerBorrower, CopyConstruct) { - auto* refcount = new common_internal::ReferenceCounted(); - Owner owner1 = Owner::ReferenceCount(refcount); - common_internal::StrongUnref(refcount); - Owner owner2(owner1); - Borrower borrower(owner1); - EXPECT_EQ(owner1, owner2); - EXPECT_EQ(owner1, borrower); - EXPECT_EQ(borrower, owner1); -} - -TEST(OwnerBorrower, MoveConstruct) { - auto* refcount = new common_internal::ReferenceCounted(); - Owner owner1 = Owner::ReferenceCount(refcount); - common_internal::StrongUnref(refcount); - Owner owner2(std::move(owner1)); - Borrower borrower(owner2); - EXPECT_EQ(owner2, borrower); - EXPECT_EQ(borrower, owner2); -} - -TEST(OwnerBorrower, CopyAssign) { - auto* refcount = new common_internal::ReferenceCounted(); - Owner owner1 = Owner::ReferenceCount(refcount); - common_internal::StrongUnref(refcount); - Owner owner2; - owner2 = owner1; - Borrower borrower(owner1); - EXPECT_EQ(owner1, owner2); - EXPECT_EQ(owner1, borrower); - EXPECT_EQ(borrower, owner1); -} - -TEST(OwnerBorrower, MoveAssign) { - auto* refcount = new common_internal::ReferenceCounted(); - Owner owner1 = Owner::ReferenceCount(refcount); - common_internal::StrongUnref(refcount); - Owner owner2; - owner2 = std::move(owner1); - Borrower borrower(owner2); - EXPECT_EQ(owner2, borrower); - EXPECT_EQ(borrower, owner2); -} - -TEST(Unique, ToAddress) { - Unique unique; - EXPECT_EQ(cel::to_address(unique), nullptr); - unique = AllocateUnique(NewDeleteAllocator<>{}); - EXPECT_EQ(cel::to_address(unique), unique.operator->()); -} - -class OwnedTest : public TestWithParam { - public: - Allocator<> GetAllocator() { - switch (GetParam()) { - case AllocatorKind::kArena: - return ArenaAllocator<>{&arena_}; - case AllocatorKind::kNewDelete: - return NewDeleteAllocator<>{}; - } - } - - private: - google::protobuf::Arena arena_; -}; - -TEST_P(OwnedTest, Default) { - Owned owned; - EXPECT_FALSE(owned); - EXPECT_EQ(cel::to_address(owned), nullptr); - EXPECT_FALSE(owned != nullptr); - EXPECT_FALSE(nullptr != owned); -} - -class TestData final : public Data { - public: - using InternalArenaConstructable_ = void; - using DestructorSkippable_ = void; - - TestData() noexcept : Data() {} - - explicit TestData(google::protobuf::Arena* absl_nullable arena) noexcept - : Data(arena) {} -}; - -TEST_P(OwnedTest, AllocateSharedData) { - auto owned = AllocateShared(GetAllocator()); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - EXPECT_EQ(Owner(owned).arena(), GetAllocator().arena()); - EXPECT_EQ(Borrower(owned).arena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, AllocateSharedMessageLite) { - auto owned = AllocateShared(GetAllocator()); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - EXPECT_EQ(Owner(owned).arena(), GetAllocator().arena()); - EXPECT_EQ(Borrower(owned).arena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, WrapSharedData) { - auto owned = - WrapShared(google::protobuf::Arena::Create(GetAllocator().arena())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - EXPECT_EQ(Owner(owned).arena(), GetAllocator().arena()); - EXPECT_EQ(Borrower(owned).arena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, WrapSharedMessageLite) { - auto owned = WrapShared( - google::protobuf::Arena::Create(GetAllocator().arena())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - EXPECT_EQ(Owner(owned).arena(), GetAllocator().arena()); - EXPECT_EQ(Borrower(owned).arena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, SharedFromUniqueData) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - EXPECT_EQ(Owner(owned).arena(), GetAllocator().arena()); - EXPECT_EQ(Borrower(owned).arena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, SharedFromUniqueMessageLite) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - EXPECT_EQ(Owner(owned).arena(), GetAllocator().arena()); - EXPECT_EQ(Borrower(owned).arena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, CopyConstruct) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - Owned copied_owned(owned); - EXPECT_EQ(copied_owned->GetArena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, MoveConstruct) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - Owned moved_owned(std::move(owned)); - EXPECT_EQ(moved_owned->GetArena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, CopyConstructOther) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - Owned copied_owned(owned); - EXPECT_EQ(copied_owned->GetArena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, MoveConstructOther) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - Owned moved_owned(std::move(owned)); - EXPECT_EQ(moved_owned->GetArena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, ConstructBorrowed) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - Owned borrowed_owned(Borrowed{owned}); - EXPECT_EQ(borrowed_owned->GetArena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, ConstructOwner) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - Owned owner_owned(Owner(owned), cel::to_address(owned)); - EXPECT_EQ(owner_owned->GetArena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, ConstructNullPtr) { - Owned owned(nullptr); - EXPECT_EQ(owned, nullptr); -} - -TEST_P(OwnedTest, CopyAssign) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - Owned copied_owned; - copied_owned = owned; - EXPECT_EQ(copied_owned->GetArena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, MoveAssign) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - Owned moved_owned; - moved_owned = std::move(owned); - EXPECT_EQ(moved_owned->GetArena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, CopyAssignOther) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - Owned copied_owned; - copied_owned = owned; - EXPECT_EQ(copied_owned->GetArena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, MoveAssignOther) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - Owned moved_owned; - moved_owned = std::move(owned); - EXPECT_EQ(moved_owned->GetArena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, AssignBorrowed) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - Owned borrowed_owned; - borrowed_owned = Borrowed{owned}; - EXPECT_EQ(borrowed_owned->GetArena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, AssignUnique) { - Owned owned; - owned = AllocateUnique(GetAllocator()); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); -} - -TEST_P(OwnedTest, AssignNullPtr) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - EXPECT_TRUE(owned); - owned = nullptr; - EXPECT_FALSE(owned); -} - -INSTANTIATE_TEST_SUITE_P(OwnedTest, OwnedTest, - ::testing::Values(AllocatorKind::kArena, - AllocatorKind::kNewDelete)); - -class BorrowedTest : public TestWithParam { - public: - Allocator<> GetAllocator() { - switch (GetParam()) { - case AllocatorKind::kArena: - return ArenaAllocator<>{&arena_}; - case AllocatorKind::kNewDelete: - return NewDeleteAllocator<>{}; - } - } - - private: - google::protobuf::Arena arena_; -}; - -TEST_P(BorrowedTest, Default) { - Borrowed borrowed; - EXPECT_FALSE(borrowed); - EXPECT_EQ(cel::to_address(borrowed), nullptr); - EXPECT_FALSE(borrowed != nullptr); - EXPECT_FALSE(nullptr != borrowed); -} - -TEST_P(BorrowedTest, CopyConstruct) { - auto owned = Owned(AllocateUnique(GetAllocator())); - auto borrowed = Borrowed(owned); - EXPECT_EQ(borrowed->GetArena(), GetAllocator().arena()); - Borrowed copied_borrowed(borrowed); - EXPECT_EQ(copied_borrowed->GetArena(), GetAllocator().arena()); -} - -TEST_P(BorrowedTest, MoveConstruct) { - auto owned = Owned(AllocateUnique(GetAllocator())); - auto borrowed = Borrowed(owned); - EXPECT_EQ(borrowed->GetArena(), GetAllocator().arena()); - Borrowed moved_borrowed(std::move(borrowed)); - EXPECT_EQ(moved_borrowed->GetArena(), GetAllocator().arena()); -} - -TEST_P(BorrowedTest, CopyConstructOther) { - auto owned = Owned(AllocateUnique(GetAllocator())); - auto borrowed = Borrowed(owned); - EXPECT_EQ(borrowed->GetArena(), GetAllocator().arena()); - Borrowed copied_borrowed(borrowed); - EXPECT_EQ(copied_borrowed->GetArena(), GetAllocator().arena()); -} - -TEST_P(BorrowedTest, MoveConstructOther) { - auto owned = Owned(AllocateUnique(GetAllocator())); - auto borrowed = Borrowed(owned); - EXPECT_EQ(borrowed->GetArena(), GetAllocator().arena()); - Borrowed moved_borrowed(std::move(borrowed)); - EXPECT_EQ(moved_borrowed->GetArena(), GetAllocator().arena()); -} - -TEST_P(BorrowedTest, ConstructNullPtr) { - Borrowed borrowed(nullptr); - EXPECT_FALSE(borrowed); -} - -TEST_P(BorrowedTest, CopyAssign) { - auto owned = Owned(AllocateUnique(GetAllocator())); - auto borrowed = Borrowed(owned); - EXPECT_EQ(borrowed->GetArena(), GetAllocator().arena()); - Borrowed copied_borrowed; - copied_borrowed = borrowed; - EXPECT_EQ(copied_borrowed->GetArena(), GetAllocator().arena()); -} - -TEST_P(BorrowedTest, MoveAssign) { - auto owned = Owned(AllocateUnique(GetAllocator())); - auto borrowed = Borrowed(owned); - EXPECT_EQ(borrowed->GetArena(), GetAllocator().arena()); - Borrowed moved_borrowed; - moved_borrowed = std::move(borrowed); - EXPECT_EQ(moved_borrowed->GetArena(), GetAllocator().arena()); -} - -TEST_P(BorrowedTest, CopyAssignOther) { - auto owned = Owned(AllocateUnique(GetAllocator())); - auto borrowed = Borrowed(owned); - EXPECT_EQ(borrowed->GetArena(), GetAllocator().arena()); - Borrowed copied_borrowed; - copied_borrowed = borrowed; - EXPECT_EQ(copied_borrowed->GetArena(), GetAllocator().arena()); -} - -TEST_P(BorrowedTest, MoveAssignOther) { - auto owned = Owned(AllocateUnique(GetAllocator())); - auto borrowed = Borrowed(owned); - EXPECT_EQ(borrowed->GetArena(), GetAllocator().arena()); - Borrowed moved_borrowed; - moved_borrowed = std::move(borrowed); - EXPECT_EQ(moved_borrowed->GetArena(), GetAllocator().arena()); -} - -TEST_P(BorrowedTest, AssignOwned) { - auto owned = Owned(AllocateUnique(GetAllocator())); - EXPECT_EQ(owned->GetArena(), GetAllocator().arena()); - Borrowed borrowed = owned; - EXPECT_EQ(borrowed->GetArena(), GetAllocator().arena()); -} - -TEST_P(BorrowedTest, AssignNullPtr) { - Borrowed borrowed; - borrowed = nullptr; - EXPECT_FALSE(borrowed); -} - -INSTANTIATE_TEST_SUITE_P(BorrowedTest, BorrowedTest, - ::testing::Values(AllocatorKind::kArena, - AllocatorKind::kNewDelete)); - -} // namespace -} // namespace cel diff --git a/common/value.cc b/common/value.cc index cc3a0825f..fa937bdf0 100644 --- a/common/value.cc +++ b/common/value.cc @@ -43,7 +43,6 @@ #include "absl/types/source_location.h" #include "absl/types/variant.h" #include "common/allocator.h" -#include "common/memory.h" #include "common/optional_ref.h" #include "common/type.h" #include "common/value_kind.h" @@ -1244,7 +1243,8 @@ struct OwningWellKnownTypesValueVisitor { cloned->CopyFrom(*value); return ParsedJsonListValue(cloned, arena); } - return ParsedJsonListValue(value.release(), arena); + return ParsedJsonListValue(value.try_as_arena_ptr()->get(), + arena); }), well_known_types::AsVariant(std::move(value))); } @@ -1258,23 +1258,23 @@ struct OwningWellKnownTypesValueVisitor { return ParsedJsonMapValue(cloned, arena); }, [&](well_known_types::StructPtr value) -> MapValue { - if (value.arena() != arena) { + if (value.GetOwningArena() != arena) { auto* cloned = value->New(arena); cloned->CopyFrom(*value); return ParsedJsonMapValue(cloned, arena); } - return ParsedJsonMapValue(value.release(), arena); + return ParsedJsonMapValue(value.try_as_arena_ptr()->get(), arena); }), well_known_types::AsVariant(std::move(value))); } - Value operator()(Unique value) const { + Value operator()(google::protobuf::Arena::UniquePtr value) const { if (value->GetArena() != arena) { auto* cloned = value->New(arena); cloned->CopyFrom(*value); return ParsedMessageValue(cloned, arena); } - return ParsedMessageValue(value.release(), arena); + return ParsedMessageValue(value.try_as_arena_ptr()->get(), arena); } template @@ -1344,7 +1344,8 @@ struct BorrowingWellKnownTypesValueVisitor { cloned->CopyFrom(*value); return ParsedJsonListValue(cloned, arena); } - return ParsedJsonListValue(value.release(), arena); + return ParsedJsonListValue(value.try_as_arena_ptr()->get(), + arena); }), well_known_types::AsVariant(std::move(value))); } @@ -1362,18 +1363,18 @@ struct BorrowingWellKnownTypesValueVisitor { cloned->CopyFrom(*value); return ParsedJsonMapValue(cloned, arena); } - return ParsedJsonMapValue(value.release(), arena); + return ParsedJsonMapValue(value.try_as_arena_ptr()->get(), arena); }), well_known_types::AsVariant(std::move(value))); } - Value operator()(Unique&& value) const { + Value operator()(google::protobuf::Arena::UniquePtr&& value) const { if (value->GetArena() != arena) { auto* cloned = value->New(arena); cloned->CopyFrom(*value); return ParsedMessageValue(cloned, arena); } - return ParsedMessageValue(value.release(), arena); + return ParsedMessageValue(value.try_as_arena_ptr()->get(), arena); } template diff --git a/internal/BUILD b/internal/BUILD index d6781b538..e49dd67e3 100644 --- a/internal/BUILD +++ b/internal/BUILD @@ -727,7 +727,6 @@ cc_test( ":testing_descriptor_pool", ":testing_message_factory", ":well_known_types", - "//common:memory", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/base:nullability", "@com_google_absl//absl/log:die_if_null", @@ -737,7 +736,6 @@ cc_test( "@com_google_absl//absl/strings:cord", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/time", - "@com_google_absl//absl/types:variant", "@com_google_cel_spec//proto/cel/expr/conformance/proto3:test_all_types_cc_proto", "@com_google_protobuf//:any_cc_proto", "@com_google_protobuf//:duration_cc_proto", @@ -842,12 +840,12 @@ cc_test( ":testing_descriptor_pool", ":testing_message_factory", ":well_known_types", - "//common:allocator", "//common:memory", "@com_google_absl//absl/base:no_destructor", "@com_google_absl//absl/base:nullability", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/log:die_if_null", + "@com_google_absl//absl/memory", "@com_google_absl//absl/status:status_matchers", "@com_google_absl//absl/strings", "@com_google_absl//absl/strings:cord", diff --git a/internal/message_equality.cc b/internal/message_equality.cc index 34080e6b1..921753222 100644 --- a/internal/message_equality.cc +++ b/internal/message_equality.cc @@ -462,7 +462,7 @@ absl::StatusOr MapValueAsEquatableValue( MessageFactory* absl_nonnull factory, EquatableValueReflection& reflection, const google::protobuf::MapValueConstRef& value, const FieldDescriptor* absl_nonnull field, std::string& scratch, - Unique& unpacked) { + google::protobuf::Arena::UniquePtr& unpacked) { if (IsAnyField(field)) { CEL_ASSIGN_OR_RETURN(unpacked, well_known_types::UnpackAnyIfResolveable( arena, reflection.any_reflection, @@ -516,7 +516,8 @@ absl::StatusOr RepeatedFieldAsEquatableValue( google::protobuf::Arena* absl_nonnull arena, const DescriptorPool* absl_nonnull pool, MessageFactory* absl_nonnull factory, EquatableValueReflection& reflection, const Message& message, const FieldDescriptor* absl_nonnull field, - int index, std::string& scratch, Unique& unpacked) { + int index, std::string& scratch, + google::protobuf::Arena::UniquePtr& unpacked) { if (IsAnyField(field)) { const auto& field_value = message.GetReflection()->GetRepeatedMessage(message, field, index); @@ -834,8 +835,8 @@ class MessageEqualsState final { auto rhs_well_known_type = rhs_descriptor->well_known_type(); const Message* absl_nonnull lhs_ptr = &lhs; const Message* absl_nonnull rhs_ptr = &rhs; - Unique lhs_unpacked; - Unique rhs_unpacked; + google::protobuf::Arena::UniquePtr lhs_unpacked; + google::protobuf::Arena::UniquePtr rhs_unpacked; // Deal with any first. We could in theory check if we should bother // unpacking, but that is more complicated. We can always implement it // later. @@ -906,9 +907,9 @@ class MessageEqualsState final { } auto lhs_begin = ConstMapBegin(*lhs_reflection, lhs, *lhs_field); const auto lhs_end = ConstMapEnd(*lhs_reflection, lhs, *lhs_field); - Unique lhs_unpacked; + google::protobuf::Arena::UniquePtr lhs_unpacked; EquatableValue lhs_value; - Unique rhs_unpacked; + google::protobuf::Arena::UniquePtr rhs_unpacked; EquatableValue rhs_value; google::protobuf::MapKey rhs_map_key; google::protobuf::MapValueConstRef rhs_map_value; @@ -960,9 +961,9 @@ class MessageEqualsState final { if (size != rhs_reflection->FieldSize(rhs, rhs_field)) { return false; } - Unique lhs_unpacked; + google::protobuf::Arena::UniquePtr lhs_unpacked; EquatableValue lhs_value; - Unique rhs_unpacked; + google::protobuf::Arena::UniquePtr rhs_unpacked; EquatableValue rhs_value; for (int i = 0; i < size; ++i) { CEL_ASSIGN_OR_RETURN(lhs_value, @@ -1007,8 +1008,8 @@ class MessageEqualsState final { } const Message* absl_nonnull lhs_ptr = &lhs; const Message* absl_nonnull rhs_ptr = &rhs; - Unique lhs_unpacked; - Unique rhs_unpacked; + google::protobuf::Arena::UniquePtr lhs_unpacked; + google::protobuf::Arena::UniquePtr rhs_unpacked; if (lhs_field != nullptr && IsAnyField(lhs_field)) { CEL_ASSIGN_OR_RETURN(lhs_unpacked, well_known_types::UnpackAnyIfResolveable( @@ -1093,7 +1094,7 @@ class MessageEqualsState final { return false; } const Message* absl_nullable rhs_packed = nullptr; - Unique rhs_unpacked; + google::protobuf::Arena::UniquePtr rhs_unpacked; if (rhs_field != nullptr && IsAnyField(rhs_field)) { rhs_packed = &rhs.GetReflection()->GetMessage(rhs, rhs_field); } else if (rhs_field == nullptr && IsAny(rhs)) { @@ -1174,7 +1175,7 @@ class MessageEqualsState final { return false; } const Message* absl_nullable lhs_packed = nullptr; - Unique lhs_unpacked; + google::protobuf::Arena::UniquePtr lhs_unpacked; if (lhs_field != nullptr && IsAnyField(lhs_field)) { lhs_packed = &lhs.GetReflection()->GetMessage(lhs, lhs_field); } else if (lhs_field == nullptr && IsAny(lhs)) { @@ -1262,7 +1263,7 @@ class MessageEqualsState final { return false; } const Message* absl_nullable rhs_packed = nullptr; - Unique rhs_unpacked; + google::protobuf::Arena::UniquePtr rhs_unpacked; if (rhs_field != nullptr && IsAnyField(rhs_field)) { rhs_packed = &rhs.GetReflection()->GetMessage(rhs, rhs_field); } else if (rhs_field == nullptr && IsAny(rhs)) { @@ -1342,7 +1343,7 @@ class MessageEqualsState final { return false; } const Message* absl_nullable lhs_packed = nullptr; - Unique lhs_unpacked; + google::protobuf::Arena::UniquePtr lhs_unpacked; if (lhs_field != nullptr && IsAnyField(lhs_field)) { lhs_packed = &lhs.GetReflection()->GetMessage(lhs, lhs_field); } else if (lhs_field == nullptr && IsAny(lhs)) { diff --git a/internal/message_equality_test.cc b/internal/message_equality_test.cc index 092edd71b..c08116181 100644 --- a/internal/message_equality_test.cc +++ b/internal/message_equality_test.cc @@ -14,6 +14,7 @@ #include "internal/message_equality.h" +#include #include #include #include @@ -27,12 +28,12 @@ #include "absl/base/nullability.h" #include "absl/log/absl_check.h" #include "absl/log/die_if_null.h" +#include "absl/memory/memory.h" #include "absl/status/status_matchers.h" #include "absl/strings/cord.h" #include "absl/strings/str_cat.h" #include "absl/strings/string_view.h" #include "absl/types/optional.h" -#include "common/allocator.h" #include "common/memory.h" #include "internal/message_type_name.h" #include "internal/parse_text_proto.h" @@ -394,7 +395,7 @@ void PackMessageTo(const google::protobuf::Message& message, google::protobuf::M reflection.SetValue(instance, value); } -absl::optional, +absl::optional, const google::protobuf::FieldDescriptor* absl_nonnull>> PackTestAllTypesProto3Field(const google::protobuf::Message& message, const google::protobuf::FieldDescriptor* absl_nonnull field) { @@ -405,7 +406,7 @@ PackTestAllTypesProto3Field(const google::protobuf::Message& message, field->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) { const auto* descriptor = message.GetDescriptor(); const auto* any_field = descriptor->FindFieldByName("repeated_any"); - auto packed = WrapShared(message.New(), NewDeleteAllocator<>{}); + auto packed = absl::WrapUnique(message.New()); const int size = message.GetReflection()->FieldSize(message, field); for (int i = 0; i < size; ++i) { PackMessageTo( @@ -413,17 +414,17 @@ PackTestAllTypesProto3Field(const google::protobuf::Message& message, packed->GetReflection()->AddMessage(cel::to_address(packed), any_field)); } - return std::pair{packed, any_field}; + return std::pair{std::move(packed), any_field}; } if (!field->is_repeated() && field->type() == google::protobuf::FieldDescriptor::TYPE_MESSAGE) { const auto* descriptor = message.GetDescriptor(); const auto* any_field = descriptor->FindFieldByName("single_any"); - auto packed = WrapShared(message.New(), NewDeleteAllocator<>{}); + auto packed = absl::WrapUnique(message.New()); PackMessageTo(message.GetReflection()->GetMessage(message, field), packed->GetReflection()->MutableMessage( cel::to_address(packed), any_field)); - return std::pair{packed, any_field}; + return std::pair{std::move(packed), any_field}; } return std::nullopt; } @@ -499,10 +500,10 @@ TEST_P(UnaryMessageFieldEqualsTest, Equals) { << rhs_field->name(); } // Test `google.protobuf.Any`. - absl::optional, + absl::optional, const google::protobuf::FieldDescriptor* absl_nonnull>> lhs_any = PackTestAllTypesProto3Field(*lhs_message, lhs_field); - absl::optional, + absl::optional, const google::protobuf::FieldDescriptor* absl_nonnull>> rhs_any = PackTestAllTypesProto3Field(*rhs_message, rhs_field); if (lhs_any) { diff --git a/internal/well_known_types.cc b/internal/well_known_types.cc index 5232bb6ad..f48d77f7f 100644 --- a/internal/well_known_types.cc +++ b/internal/well_known_types.cc @@ -1489,7 +1489,7 @@ google::protobuf::Message* absl_nonnull ValueReflection::MutableStructValue( return message->GetReflection()->MutableMessage(message, struct_value_field_); } -Unique ValueReflection::ReleaseListValue( +google::protobuf::Arena::UniquePtr ValueReflection::ReleaseListValue( google::protobuf::Message* absl_nonnull message) const { ABSL_DCHECK(IsInitialized()); ABSL_DCHECK_EQ(message->GetDescriptor(), descriptor_); @@ -1497,12 +1497,12 @@ Unique ValueReflection::ReleaseListValue( if (!reflection->HasField(*message, list_value_field_)) { reflection->MutableMessage(message, list_value_field_); } - return WrapUnique( - reflection->UnsafeArenaReleaseMessage(message, list_value_field_), - message->GetArena()); + return google::protobuf::Arena::UnsafeWrapUniquePtr( + message->GetArena(), + reflection->UnsafeArenaReleaseMessage(message, list_value_field_)); } -Unique ValueReflection::ReleaseStructValue( +google::protobuf::Arena::UniquePtr ValueReflection::ReleaseStructValue( google::protobuf::Message* absl_nonnull message) const { ABSL_DCHECK(IsInitialized()); ABSL_DCHECK_EQ(message->GetDescriptor(), descriptor_); @@ -1510,9 +1510,9 @@ Unique ValueReflection::ReleaseStructValue( if (!reflection->HasField(*message, struct_value_field_)) { reflection->MutableMessage(message, struct_value_field_); } - return WrapUnique( - reflection->UnsafeArenaReleaseMessage(message, struct_value_field_), - message->GetArena()); + return google::protobuf::Arena::UnsafeWrapUniquePtr( + message->GetArena(), + reflection->UnsafeArenaReleaseMessage(message, struct_value_field_)); } absl::StatusOr GetValueReflection( @@ -1899,9 +1899,9 @@ namespace { // it as `ListValue`. If adapted is empty, we return as a reference. If adapted // is present, message must be a reference to the value held in adapted and it // will be returned by value. -absl::StatusOr AdaptListValue(google::protobuf::Arena* absl_nullable arena, - const google::protobuf::Message& message, - Unique adapted) { +absl::StatusOr AdaptListValue( + google::protobuf::Arena* absl_nullable arena, const google::protobuf::Message& message, + google::protobuf::Arena::UniquePtr adapted) { ABSL_DCHECK(!adapted || &message == cel::to_address(adapted)); const auto* descriptor = message.GetDescriptor(); if (ABSL_PREDICT_FALSE(descriptor == nullptr)) { @@ -1922,9 +1922,9 @@ absl::StatusOr AdaptListValue(google::protobuf::Arena* absl_nullable // as `Struct`. If adapted is empty, we return as a reference. If adapted is // present, message must be a reference to the value held in adapted and it will // be returned by value. -absl::StatusOr AdaptStruct(google::protobuf::Arena* absl_nullable arena, - const google::protobuf::Message& message, - Unique adapted) { +absl::StatusOr AdaptStruct( + google::protobuf::Arena* absl_nullable arena, const google::protobuf::Message& message, + google::protobuf::Arena::UniquePtr adapted) { ABSL_DCHECK(!adapted || &message == cel::to_address(adapted)); const auto* descriptor = message.GetDescriptor(); if (ABSL_PREDICT_FALSE(descriptor == nullptr)) { @@ -1942,14 +1942,14 @@ absl::StatusOr AdaptStruct(google::protobuf::Arena* absl_nullable arena, // AdaptAny recursively unpacks a protocol buffer message which is an instance // of `google.protobuf.Any`. -absl::StatusOr> AdaptAny( +absl::StatusOr> AdaptAny( google::protobuf::Arena* absl_nullable arena, AnyReflection& reflection, const google::protobuf::Message& message, const Descriptor* absl_nonnull descriptor, const DescriptorPool* absl_nonnull pool, google::protobuf::MessageFactory* absl_nonnull factory, bool error_if_unresolveable) { ABSL_DCHECK_EQ(descriptor->well_known_type(), Descriptor::WELLKNOWNTYPE_ANY); const google::protobuf::Message* absl_nonnull to_unwrap = &message; - Unique unwrapped; + google::protobuf::Arena::UniquePtr unwrapped; std::string type_url_scratch; std::string value_scratch; do { @@ -1979,7 +1979,8 @@ absl::StatusOr> AdaptAny( "unable to build prototype for type name: ", type_url_view)); } BytesValue value = reflection.GetValue(*to_unwrap, value_scratch); - Unique unpacked = WrapUnique(prototype->New(arena), arena); + google::protobuf::Arena::UniquePtr unpacked = + google::protobuf::Arena::UnsafeWrapUniquePtr(arena, prototype->New(arena)); // TODO(b/557267722): Extensions that are not included in the same // descriptor pool as the resolved descriptor will be treated as unknown // fields. Extending messages like this should be exceedingly rare and is @@ -2014,7 +2015,7 @@ absl::StatusOr> AdaptAny( } // namespace -absl::StatusOr> UnpackAnyFrom( +absl::StatusOr> UnpackAnyFrom( google::protobuf::Arena* absl_nullable arena, AnyReflection& reflection, const google::protobuf::Message& message, const google::protobuf::DescriptorPool* absl_nonnull pool, @@ -2025,11 +2026,12 @@ absl::StatusOr> UnpackAnyFrom( factory, /*error_if_unresolveable=*/true); } -absl::StatusOr> UnpackAnyIfResolveable( - google::protobuf::Arena* absl_nullable arena, AnyReflection& reflection, - const google::protobuf::Message& message, - const google::protobuf::DescriptorPool* absl_nonnull pool, - google::protobuf::MessageFactory* absl_nonnull factory) { +absl::StatusOr> +UnpackAnyIfResolveable(google::protobuf::Arena* absl_nullable arena, + AnyReflection& reflection, + const google::protobuf::Message& message, + const google::protobuf::DescriptorPool* absl_nonnull pool, + google::protobuf::MessageFactory* absl_nonnull factory) { ABSL_DCHECK_EQ(message.GetDescriptor()->well_known_type(), Descriptor::WELLKNOWNTYPE_ANY); return AdaptAny(arena, reflection, message, message.GetDescriptor(), pool, @@ -2047,7 +2049,7 @@ absl::StatusOr AdaptFromMessage( message.GetTypeName())); } const google::protobuf::Message* absl_nonnull to_adapt; - Unique adapted; + google::protobuf::Arena::UniquePtr adapted; Descriptor::WellKnownType well_known_type = descriptor->well_known_type(); if (well_known_type == Descriptor::WELLKNOWNTYPE_ANY) { AnyReflection reflection; diff --git a/internal/well_known_types.h b/internal/well_known_types.h index f63e5e76b..3e09b286b 100644 --- a/internal/well_known_types.h +++ b/internal/well_known_types.h @@ -50,7 +50,6 @@ #include "absl/time/time.h" #include "absl/types/variant.h" #include "common/any.h" -#include "common/memory.h" #include "google/protobuf/arena.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/map_field.h" @@ -1007,10 +1006,10 @@ class ValueReflection final { google::protobuf::Message* absl_nonnull MutableStructValue( google::protobuf::Message* absl_nonnull message) const; - Unique ReleaseListValue( + google::protobuf::Arena::UniquePtr ReleaseListValue( google::protobuf::Message* absl_nonnull message) const; - Unique ReleaseStructValue( + google::protobuf::Arena::UniquePtr ReleaseStructValue( google::protobuf::Message* absl_nonnull message) const; private: @@ -1278,18 +1277,18 @@ absl::StatusOr GetFieldMaskReflection( const google::protobuf::Descriptor* absl_nonnull descriptor ABSL_ATTRIBUTE_LIFETIME_BOUND); -using ListValuePtr = Unique; +using ListValuePtr = google::protobuf::Arena::UniquePtr; using ListValueConstRef = std::reference_wrapper; -using StructPtr = Unique; +using StructPtr = google::protobuf::Arena::UniquePtr; using StructConstRef = std::reference_wrapper; // Variant holding `std::reference_wrapper` or `Unique`, either of which is an -// instance of `google.protobuf.ListValue` which is either a generated message -// or dynamic message. +// google::protobuf::Message>` or `google::protobuf::Arena::UniquePtr`, either of +// which is an instance of `google.protobuf.ListValue` which is either a +// generated message or dynamic message. class ListValue final : public absl::variant { using absl::variant::variant; }; @@ -1316,9 +1315,9 @@ inline absl::variant&& AsVariant( } // Variant holding `std::reference_wrapper` or `Unique`, either of which is an -// instance of `google.protobuf.Struct` which is either a generated message or -// dynamic message. +// google::protobuf::Message>` or `google::protobuf::Arena::UniquePtr`, either of +// which is an instance of `google.protobuf.Struct` which is either a generated +// message or dynamic message. class Struct final : public absl::variant { public: using absl::variant::variant; @@ -1342,13 +1341,14 @@ inline absl::variant&& AsVariant(Struct&& value) { } // Variant capable of representing any unwrapped well known type or message. -using Value = absl::variant>; +using Value = + absl::variant>; // Unpacks the given instance of `google.protobuf.Any`. -absl::StatusOr> UnpackAnyFrom( +absl::StatusOr> UnpackAnyFrom( google::protobuf::Arena* absl_nullable arena ABSL_ATTRIBUTE_LIFETIME_BOUND, AnyReflection& reflection, const google::protobuf::Message& message, const google::protobuf::DescriptorPool* absl_nonnull pool @@ -1356,7 +1356,8 @@ absl::StatusOr> UnpackAnyFrom( google::protobuf::MessageFactory* absl_nonnull factory ABSL_ATTRIBUTE_LIFETIME_BOUND); // Unpacks the given instance of `google.protobuf.Any` if it is resolvable. -absl::StatusOr> UnpackAnyIfResolveable( +absl::StatusOr> +UnpackAnyIfResolveable( google::protobuf::Arena* absl_nullable arena ABSL_ATTRIBUTE_LIFETIME_BOUND, AnyReflection& reflection, const google::protobuf::Message& message, const google::protobuf::DescriptorPool* absl_nonnull pool diff --git a/internal/well_known_types_test.cc b/internal/well_known_types_test.cc index 5ffc06ee9..aae66c51c 100644 --- a/internal/well_known_types_test.cc +++ b/internal/well_known_types_test.cc @@ -34,8 +34,6 @@ #include "absl/strings/cord.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" -#include "absl/types/variant.h" -#include "common/memory.h" #include "internal/message_type_name.h" #include "internal/minimal_descriptor_pool.h" #include "internal/parse_text_proto.h" @@ -1027,8 +1025,10 @@ TEST_F(AdaptFromMessageTest, Any_Struct) { TEST_F(AdaptFromMessageTest, Any_TestAllTypesProto3) { auto message = DynamicParseTextProto( R"pb(type_url: "type.googleapis.com/cel.expr.conformance.proto3.TestAllTypes")pb"); - EXPECT_THAT(AdaptFromMessage(*message), - IsOkAndHolds(VariantWith>(NotNull()))); + EXPECT_THAT( + AdaptFromMessage(*message), + IsOkAndHolds( + VariantWith>(NotNull()))); } TEST_F(AdaptFromMessageTest, Any_BadTypeUrlDomain) {