Skip to content

Commit f86575b

Browse files
jckingcopybara-github
authored andcommitted
Allow dynamically building ListValue, MapValue, and StructValue
PiperOrigin-RevId: 534106408
1 parent f7210ed commit f86575b

14 files changed

Lines changed: 441 additions & 4 deletions

base/BUILD

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ cc_library(
4646
deps = [
4747
"//base/internal:data",
4848
"//base/internal:handle",
49+
"@com_google_absl//absl/base",
4950
"@com_google_absl//absl/base:core_headers",
5051
"@com_google_absl//absl/log:absl_check",
5152
],

base/handle.h

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@
1515
#ifndef THIRD_PARTY_CEL_CPP_BASE_HANDLE_H_
1616
#define THIRD_PARTY_CEL_CPP_BASE_HANDLE_H_
1717

18+
#include <memory>
19+
#include <string>
1820
#include <type_traits>
1921
#include <utility>
2022

2123
#include "absl/base/attributes.h"
24+
#include "absl/base/casts.h"
25+
#include "absl/base/macros.h"
2226
#include "absl/log/absl_check.h"
2327
#include "base/internal/data.h"
2428
#include "base/internal/handle.h" // IWYU pragma: export
@@ -302,6 +306,52 @@ struct HandleFactory {
302306
template <typename F, typename... Args>
303307
static std::enable_if_t<IsDerivedHeapDataV<F>, Handle<T>> Make(
304308
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+
}
305355
};
306356

307357
} // namespace cel::base_internal

base/types/list_type.cc

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@
2222
#include "absl/strings/string_view.h"
2323
#include "absl/types/span.h"
2424
#include "base/internal/data.h"
25+
#include "base/kind.h"
26+
#include "base/memory.h"
2527
#include "base/types/dyn_type.h"
28+
#include "base/value_factory.h"
29+
#include "base/values/list_value.h"
30+
#include "base/values/list_value_builder.h"
2631

2732
namespace cel {
2833

@@ -48,6 +53,40 @@ const Handle<Type>& ListType::element() const {
4853
return static_cast<const base_internal::ModernListType&>(*this).element();
4954
}
5055

56+
absl::StatusOr<UniqueRef<ListValueBuilderInterface>> ListType::NewValueBuilder(
57+
ValueFactory& value_factory) const {
58+
switch (element()->kind()) {
59+
case Kind::kBool:
60+
return MakeUnique<ListValueBuilder<BoolValue>>(
61+
value_factory.memory_manager(), base_internal::kComposedListType,
62+
value_factory, handle_from_this());
63+
case Kind::kInt:
64+
return MakeUnique<ListValueBuilder<IntValue>>(
65+
value_factory.memory_manager(), base_internal::kComposedListType,
66+
value_factory, handle_from_this());
67+
case Kind::kUint:
68+
return MakeUnique<ListValueBuilder<UintValue>>(
69+
value_factory.memory_manager(), base_internal::kComposedListType,
70+
value_factory, handle_from_this());
71+
case Kind::kDouble:
72+
return MakeUnique<ListValueBuilder<DoubleValue>>(
73+
value_factory.memory_manager(), base_internal::kComposedListType,
74+
value_factory, handle_from_this());
75+
case Kind::kDuration:
76+
return MakeUnique<ListValueBuilder<DurationValue>>(
77+
value_factory.memory_manager(), base_internal::kComposedListType,
78+
value_factory, handle_from_this());
79+
case Kind::kTimestamp:
80+
return MakeUnique<ListValueBuilder<TimestampValue>>(
81+
value_factory.memory_manager(), base_internal::kComposedListType,
82+
value_factory, handle_from_this());
83+
default:
84+
return MakeUnique<ListValueBuilder<Value>>(
85+
value_factory.memory_manager(), base_internal::kComposedListType,
86+
value_factory, handle_from_this());
87+
}
88+
}
89+
5190
namespace base_internal {
5291

5392
const Handle<Type>& LegacyListType::element() const {

base/types/list_type.h

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919
#include <cstdint>
2020
#include <string>
2121

22+
#include "absl/base/attributes.h"
2223
#include "absl/log/absl_check.h"
24+
#include "absl/status/statusor.h"
2325
#include "absl/strings/string_view.h"
2426
#include "absl/types/span.h"
27+
#include "base/handle.h"
2528
#include "base/internal/data.h"
2629
#include "base/kind.h"
2730
#include "base/memory.h"
@@ -31,10 +34,14 @@ namespace cel {
3134

3235
class MemoryManager;
3336
class ListValue;
37+
class ValueFactory;
38+
class ListValueBuilderInterface;
3439

3540
// ListType represents a list type. A list is a sequential container where each
3641
// element is the same type.
37-
class ListType : public Type {
42+
class ListType
43+
: public Type,
44+
public base_internal::EnableHandleFromThis<ListType, ListType> {
3845
public:
3946
static constexpr Kind kKind = Kind::kList;
4047

@@ -56,6 +63,10 @@ class ListType : public Type {
5663
return static_cast<const ListType&>(type);
5764
}
5865

66+
absl::StatusOr<UniqueRef<ListValueBuilderInterface>> NewValueBuilder(
67+
ValueFactory& value_factory
68+
ABSL_ATTRIBUTE_LIFETIME_BOUND) const ABSL_ATTRIBUTE_LIFETIME_BOUND;
69+
5970
private:
6071
friend class Type;
6172
friend class MemoryManager;

base/types/map_type.cc

Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,12 @@
2222
#include "absl/strings/string_view.h"
2323
#include "absl/types/span.h"
2424
#include "base/internal/data.h"
25+
#include "base/kind.h"
26+
#include "base/memory.h"
2527
#include "base/types/dyn_type.h"
28+
#include "base/value_factory.h"
29+
#include "base/values/map_value.h"
30+
#include "base/values/map_value_builder.h"
2631

2732
namespace cel {
2833

@@ -56,6 +61,54 @@ const Handle<Type>& MapType::value() const {
5661
return static_cast<const base_internal::ModernMapType&>(*this).value();
5762
}
5863

64+
namespace {
65+
66+
template <typename K>
67+
absl::StatusOr<UniqueRef<MapValueBuilderInterface>> NewMapValueBuilderFor(
68+
ValueFactory& value_factory, Handle<MapType> type) {
69+
switch (type->value()->kind()) {
70+
case Kind::kBool:
71+
return MakeUnique<MapValueBuilder<K, BoolValue>>(
72+
value_factory.memory_manager(), value_factory, std::move(type));
73+
case Kind::kInt:
74+
return MakeUnique<MapValueBuilder<K, IntValue>>(
75+
value_factory.memory_manager(), value_factory, std::move(type));
76+
case Kind::kUint:
77+
return MakeUnique<MapValueBuilder<K, UintValue>>(
78+
value_factory.memory_manager(), value_factory, std::move(type));
79+
case Kind::kDouble:
80+
return MakeUnique<MapValueBuilder<K, DoubleValue>>(
81+
value_factory.memory_manager(), value_factory, std::move(type));
82+
case Kind::kDuration:
83+
return MakeUnique<MapValueBuilder<K, DurationValue>>(
84+
value_factory.memory_manager(), value_factory, std::move(type));
85+
case Kind::kTimestamp:
86+
return MakeUnique<MapValueBuilder<K, TimestampValue>>(
87+
value_factory.memory_manager(), value_factory, std::move(type));
88+
default:
89+
return MakeUnique<MapValueBuilder<K, Value>>(
90+
value_factory.memory_manager(), value_factory, std::move(type));
91+
}
92+
}
93+
94+
} // namespace
95+
96+
absl::StatusOr<UniqueRef<MapValueBuilderInterface>> MapType::NewValueBuilder(
97+
ValueFactory& value_factory) const {
98+
switch (key()->kind()) {
99+
case Kind::kBool:
100+
return NewMapValueBuilderFor<BoolValue>(value_factory,
101+
handle_from_this());
102+
case Kind::kInt:
103+
return NewMapValueBuilderFor<IntValue>(value_factory, handle_from_this());
104+
case Kind::kUint:
105+
return NewMapValueBuilderFor<UintValue>(value_factory,
106+
handle_from_this());
107+
default:
108+
return NewMapValueBuilderFor<Value>(value_factory, handle_from_this());
109+
}
110+
}
111+
59112
namespace base_internal {
60113

61114
const Handle<Type>& LegacyMapType::key() const {

base/types/map_type.h

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,12 @@
1919
#include <cstdint>
2020
#include <string>
2121

22+
#include "absl/base/attributes.h"
2223
#include "absl/log/absl_check.h"
24+
#include "absl/status/statusor.h"
2325
#include "absl/strings/string_view.h"
2426
#include "absl/types/span.h"
27+
#include "base/handle.h"
2528
#include "base/internal/data.h"
2629
#include "base/kind.h"
2730
#include "base/memory.h"
@@ -32,10 +35,13 @@ namespace cel {
3235
class MemoryManager;
3336
class TypeFactory;
3437
class MapValue;
38+
class ValueFactory;
39+
class MapValueBuilderInterface;
3540

3641
// MapType represents a map type. A map is container of key and value pairs
3742
// where each key appears at most once.
38-
class MapType : public Type {
43+
class MapType : public Type,
44+
public base_internal::EnableHandleFromThis<MapType, MapType> {
3945
public:
4046
static constexpr Kind kKind = Kind::kMap;
4147

@@ -60,6 +66,10 @@ class MapType : public Type {
6066
// Returns the type of the values in the map.
6167
const Handle<Type>& value() const;
6268

69+
absl::StatusOr<UniqueRef<MapValueBuilderInterface>> NewValueBuilder(
70+
ValueFactory& value_factory
71+
ABSL_ATTRIBUTE_LIFETIME_BOUND) const ABSL_ATTRIBUTE_LIFETIME_BOUND;
72+
6373
private:
6474
friend class Type;
6575
friend class MemoryManager;

base/types/struct_type.cc

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
#include "absl/strings/str_cat.h"
2424
#include "absl/strings/string_view.h"
2525
#include "absl/types/variant.h"
26+
#include "base/values/struct_value_builder.h"
2627
#include "internal/overloaded.h"
2728
#include "internal/status_macros.h"
2829

@@ -105,6 +106,11 @@ StructType::NewFieldIterator(MemoryManager& memory_manager) const {
105106
return CEL_INTERNAL_STRUCT_TYPE_DISPATCH(NewFieldIterator, memory_manager);
106107
}
107108

109+
absl::StatusOr<UniqueRef<StructValueBuilderInterface>>
110+
StructType::NewValueBuilder(ValueFactory& value_factory) const {
111+
return CEL_INTERNAL_STRUCT_TYPE_DISPATCH(NewValueBuilder, value_factory);
112+
}
113+
108114
#undef CEL_INTERNAL_STRUCT_TYPE_DISPATCH
109115

110116
struct StructType::FindFieldVisitor final {
@@ -182,6 +188,14 @@ LegacyStructType::FindFieldByNumber(TypeManager& type_manager,
182188
"Legacy struct type does not support type introspection");
183189
}
184190

191+
absl::StatusOr<UniqueRef<StructValueBuilderInterface>>
192+
LegacyStructType::NewValueBuilder(ValueFactory& value_factory) const {
193+
return absl::UnimplementedError(
194+
"StructType::NewValueBuilder is unimplemented. Perhaps the value library "
195+
"is not linked into your binary or StructType::NewValueBuilder was not "
196+
"overridden?");
197+
}
198+
185199
AbstractStructType::AbstractStructType()
186200
: StructType(), base_internal::HeapData(kKind) {
187201
// Ensure `Type*` and `base_internal::HeapData*` are not thunked.
@@ -190,6 +204,14 @@ AbstractStructType::AbstractStructType()
190204
reinterpret_cast<uintptr_t>(static_cast<base_internal::HeapData*>(this)));
191205
}
192206

207+
absl::StatusOr<UniqueRef<StructValueBuilderInterface>>
208+
AbstractStructType::NewValueBuilder(ValueFactory& value_factory) const {
209+
return absl::UnimplementedError(
210+
"StructType::NewValueBuilder is unimplemented. Perhaps the value library "
211+
"is not linked into your binary or StructType::NewValueBuilder was not "
212+
"overridden?");
213+
}
214+
193215
} // namespace base_internal
194216

195217
} // namespace cel

base/types/struct_type.h

Lines changed: 19 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
#include "absl/strings/string_view.h"
2828
#include "absl/types/optional.h"
2929
#include "absl/types/variant.h"
30+
#include "base/handle.h"
3031
#include "base/internal/data.h"
3132
#include "base/kind.h"
3233
#include "base/memory.h"
@@ -43,6 +44,8 @@ class MemoryManager;
4344
class StructValue;
4445
class TypedStructValueFactory;
4546
class TypeManager;
47+
class StructValueBuilderInterface;
48+
class ValueFactory;
4649

4750
// StructType represents an struct type. An struct is a set of fields
4851
// that can be looked up by name and/or number.
@@ -133,6 +136,10 @@ class StructType : public Type {
133136
absl::StatusOr<UniqueRef<FieldIterator>> NewFieldIterator(
134137
MemoryManager& memory_manager) const ABSL_ATTRIBUTE_LIFETIME_BOUND;
135138

139+
absl::StatusOr<UniqueRef<StructValueBuilderInterface>> NewValueBuilder(
140+
ValueFactory& value_factory
141+
ABSL_ATTRIBUTE_LIFETIME_BOUND) const ABSL_ATTRIBUTE_LIFETIME_BOUND;
142+
136143
protected:
137144
static FieldId MakeFieldId(absl::string_view name) { return FieldId(name); }
138145

@@ -256,6 +263,10 @@ class LegacyStructType final : public StructType, public InlineData {
256263
absl::StatusOr<UniqueRef<FieldIterator>> NewFieldIterator(
257264
MemoryManager& memory_manager) const ABSL_ATTRIBUTE_LIFETIME_BOUND;
258265

266+
absl::StatusOr<UniqueRef<StructValueBuilderInterface>> NewValueBuilder(
267+
ValueFactory& value_factory
268+
ABSL_ATTRIBUTE_LIFETIME_BOUND) const ABSL_ATTRIBUTE_LIFETIME_BOUND;
269+
259270
private:
260271
static constexpr uintptr_t kMetadata =
261272
kStoredInline | kTrivial | (static_cast<uintptr_t>(kKind) << kKindShift);
@@ -279,7 +290,10 @@ class LegacyStructType final : public StructType, public InlineData {
279290
uintptr_t msg_;
280291
};
281292

282-
class AbstractStructType : public StructType, public HeapData {
293+
class AbstractStructType
294+
: public StructType,
295+
public HeapData,
296+
public EnableHandleFromThis<StructType, AbstractStructType> {
283297
public:
284298
static bool Is(const Type& type) {
285299
return StructType::Is(type) &&
@@ -313,6 +327,10 @@ class AbstractStructType : public StructType, public HeapData {
313327
virtual absl::StatusOr<UniqueRef<FieldIterator>> NewFieldIterator(
314328
MemoryManager& memory_manager) const ABSL_ATTRIBUTE_LIFETIME_BOUND = 0;
315329

330+
virtual absl::StatusOr<UniqueRef<StructValueBuilderInterface>>
331+
NewValueBuilder(ValueFactory& value_factory ABSL_ATTRIBUTE_LIFETIME_BOUND)
332+
const ABSL_ATTRIBUTE_LIFETIME_BOUND;
333+
316334
protected:
317335
AbstractStructType();
318336

0 commit comments

Comments
 (0)