1818#include < type_traits>
1919
2020#include " absl/base/nullability.h"
21+ #include " absl/log/absl_check.h"
2122#include " absl/status/status.h"
2223#include " absl/strings/str_cat.h"
23- #include " common/casting.h"
2424#include " common/value.h"
2525#include " runtime/activation.h"
2626#include " google/protobuf/arena.h"
@@ -49,6 +49,43 @@ absl::Status BindProtoToActivation(
4949 google::protobuf::MessageFactory* absl_nonnull message_factory,
5050 google::protobuf::Arena* absl_nonnull arena, Activation* absl_nonnull activation);
5151
52+ template <bool kBorrow , typename T>
53+ absl::Status BindProtoToActivationImpl (
54+ const T& context, BindProtoUnsetFieldBehavior unset_field_behavior,
55+ const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
56+ google::protobuf::MessageFactory* absl_nonnull message_factory,
57+ google::protobuf::Arena* absl_nonnull arena, Activation* absl_nonnull activation) {
58+ static_assert (std::is_base_of_v<google::protobuf::Message, T>);
59+
60+ Value parent;
61+ if constexpr (kBorrow ) {
62+ parent = Value::WrapMessageUnsafe (&context, descriptor_pool,
63+ message_factory, arena);
64+ } else {
65+ parent =
66+ Value::FromMessage (context, descriptor_pool, message_factory, arena);
67+ }
68+
69+ if (!parent.IsStruct ()) {
70+ return absl::InvalidArgumentError (
71+ absl::StrCat (" context is a well-known type: " , context.GetTypeName ()));
72+ }
73+ StructValue struct_value = parent.GetStruct ();
74+
75+ const google::protobuf::Descriptor* descriptor = context.GetDescriptor ();
76+ ABSL_DCHECK (descriptor != nullptr );
77+ if (descriptor == nullptr ) {
78+ // Generally not possible, but don't crash in case of a misbehaving
79+ // implementation in normal builds.
80+ return absl::InvalidArgumentError (
81+ absl::StrCat (" context missing descriptor: " , context.GetTypeName ()));
82+ }
83+
84+ return BindProtoToActivation (*descriptor, struct_value, unset_field_behavior,
85+ descriptor_pool, message_factory, arena,
86+ activation);
87+ }
88+
5289} // namespace runtime_internal
5390
5491// Utility method, that takes a protobuf Message and interprets it as a
@@ -89,26 +126,9 @@ absl::Status BindProtoToActivation(
89126 const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
90127 google::protobuf::MessageFactory* absl_nonnull message_factory,
91128 google::protobuf::Arena* absl_nonnull arena, Activation* absl_nonnull activation) {
92- static_assert (std::is_base_of_v<google::protobuf::Message, T>);
93- Value parent =
94- Value::FromMessage (context, descriptor_pool, message_factory, arena);
95-
96- if (!InstanceOf<StructValue>(parent)) {
97- return absl::InvalidArgumentError (
98- absl::StrCat (" context is a well-known type: " , context.GetTypeName ()));
99- }
100- const StructValue& struct_value = Cast<StructValue>(parent);
101-
102- const google::protobuf::Descriptor* descriptor = context.GetDescriptor ();
103-
104- if (descriptor == nullptr ) {
105- return absl::InvalidArgumentError (
106- absl::StrCat (" context missing descriptor: " , context.GetTypeName ()));
107- }
108-
109- return runtime_internal::BindProtoToActivation (
110- *descriptor, struct_value, unset_field_behavior, descriptor_pool,
111- message_factory, arena, activation);
129+ return runtime_internal::BindProtoToActivationImpl<false >(
130+ context, unset_field_behavior, descriptor_pool, message_factory, arena,
131+ activation);
112132}
113133
114134template <typename T>
@@ -122,6 +142,33 @@ absl::Status BindProtoToActivation(
122142 activation);
123143}
124144
145+ // Like `BindProtoToActivation`, but uses `Value::WrapMessageUnsafe` to borrow
146+ // from `context` rather than copying fields to `arena`.
147+ //
148+ // Requires the caller to keep the context message valid as long as the
149+ // activation or any derived value.
150+ template <typename T>
151+ absl::Status BindProtoViewToActivation (
152+ const T& context, BindProtoUnsetFieldBehavior unset_field_behavior,
153+ const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
154+ google::protobuf::MessageFactory* absl_nonnull message_factory,
155+ google::protobuf::Arena* absl_nonnull arena, Activation* absl_nonnull activation) {
156+ return runtime_internal::BindProtoToActivationImpl<true >(
157+ context, unset_field_behavior, descriptor_pool, message_factory, arena,
158+ activation);
159+ }
160+
161+ template <typename T>
162+ absl::Status BindProtoViewToActivation (
163+ const T& context,
164+ const google::protobuf::DescriptorPool* absl_nonnull descriptor_pool,
165+ google::protobuf::MessageFactory* absl_nonnull message_factory,
166+ google::protobuf::Arena* absl_nonnull arena, Activation* absl_nonnull activation) {
167+ return BindProtoViewToActivation (context, BindProtoUnsetFieldBehavior::kSkip ,
168+ descriptor_pool, message_factory, arena,
169+ activation);
170+ }
171+
125172} // namespace cel
126173
127174#endif // THIRD_PARTY_CEL_CPP_RUNTIME_BIND_PROTO_TO_ACTIVATION_H_
0 commit comments