|
15 | 15 | #ifndef THIRD_PARTY_CEL_CPP_BASE_HANDLE_H_ |
16 | 16 | #define THIRD_PARTY_CEL_CPP_BASE_HANDLE_H_ |
17 | 17 |
|
| 18 | +#include <memory> |
| 19 | +#include <string> |
18 | 20 | #include <type_traits> |
19 | 21 | #include <utility> |
20 | 22 |
|
21 | 23 | #include "absl/base/attributes.h" |
| 24 | +#include "absl/base/casts.h" |
| 25 | +#include "absl/base/macros.h" |
22 | 26 | #include "absl/log/absl_check.h" |
23 | 27 | #include "base/internal/data.h" |
24 | 28 | #include "base/internal/handle.h" // IWYU pragma: export |
@@ -302,6 +306,52 @@ struct HandleFactory { |
302 | 306 | template <typename F, typename... Args> |
303 | 307 | static std::enable_if_t<IsDerivedHeapDataV<F>, Handle<T>> Make( |
304 | 308 | MemoryManager& memory_manager, Args&&... args); |
| 309 | + |
| 310 | + // Constructs a handle from `*this` for classes which extend `Type` and |
| 311 | + // `Value`. |
| 312 | + template <typename F> |
| 313 | + static Handle<T> FromThis(F& self) { |
| 314 | + if constexpr (std::is_base_of_v<InlineData, F>) { |
| 315 | + // If F is derived from InlineData, we don't need to perform runtime |
| 316 | + // checks. This is selected at compile time. |
| 317 | + return Handle<T>(*absl::bit_cast<const Handle<F>*>( |
| 318 | + static_cast<Data*>(std::addressof(self)))); |
| 319 | + } |
| 320 | + if constexpr (std::is_base_of_v<HeapData, F>) { |
| 321 | + // If F is derived from HeapData, we don't need to perform runtime checks. |
| 322 | + // This is selected at compile time. |
| 323 | + if (Metadata::IsReferenceCounted(self)) { |
| 324 | + Metadata::Ref(self); |
| 325 | + return Handle<T>(kInPlaceReferenceCounted, self); |
| 326 | + } |
| 327 | + // Must be arena allocated. |
| 328 | + ABSL_ASSERT(Metadata::IsArenaAllocated(self)); |
| 329 | + return Handle<T>(kInPlaceArenaAllocated, self); |
| 330 | + } |
| 331 | + // Perform runtime checks, F is not derived from InlineData or HeapData so |
| 332 | + // it must be a abstract base class. |
| 333 | + if (Metadata::IsStoredInline(self)) { |
| 334 | + return Handle<T>(*absl::bit_cast<const Handle<F>*>( |
| 335 | + static_cast<Data*>(std::addressof(self)))); |
| 336 | + } |
| 337 | + // Must be heap allocated. |
| 338 | + if (Metadata::IsReferenceCounted(self)) { |
| 339 | + Metadata::Ref(self); |
| 340 | + return Handle<T>(kInPlaceReferenceCounted, self); |
| 341 | + } |
| 342 | + // Must be arena allocated. |
| 343 | + ABSL_ASSERT(Metadata::IsArenaAllocated(self)); |
| 344 | + return Handle<T>(kInPlaceArenaAllocated, self); |
| 345 | + } |
| 346 | +}; |
| 347 | + |
| 348 | +template <typename BaseT, typename DerivedT> |
| 349 | +struct EnableHandleFromThis { |
| 350 | + protected: |
| 351 | + Handle<BaseT> handle_from_this() const { |
| 352 | + return HandleFactory<BaseT>::FromThis( |
| 353 | + const_cast<DerivedT&>(*reinterpret_cast<const DerivedT*>(this))); |
| 354 | + } |
305 | 355 | }; |
306 | 356 |
|
307 | 357 | } // namespace cel::base_internal |
|
0 commit comments