Skip to content

Commit 05556a0

Browse files
jnthntatumcopybara-github
authored andcommitted
Add wrapping version of BindProtoToActivation.
PiperOrigin-RevId: 945797968
1 parent 4c95b4f commit 05556a0

4 files changed

Lines changed: 104 additions & 22 deletions

File tree

extensions/protobuf/bind_proto_to_activation.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ using BindProtoUnsetFieldBehavior ABSL_DEPRECATED(
2525
::cel::BindProtoUnsetFieldBehavior;
2626

2727
using ::cel::BindProtoToActivation;
28+
using ::cel::BindProtoViewToActivation;
2829

2930
namespace protobuf_internal {
3031

runtime/BUILD

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,10 +116,10 @@ cc_library(
116116
hdrs = ["bind_proto_to_activation.h"],
117117
deps = [
118118
":activation",
119-
"//common:casting",
120119
"//common:value",
121120
"//internal:status_macros",
122121
"@com_google_absl//absl/base:nullability",
122+
"@com_google_absl//absl/log:absl_check",
123123
"@com_google_absl//absl/status",
124124
"@com_google_absl//absl/status:statusor",
125125
"@com_google_absl//absl/strings",

runtime/bind_proto_to_activation.h

Lines changed: 68 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,9 @@
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

114134
template <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_

runtime/bind_proto_to_activation_test.cc

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,5 +240,39 @@ TEST_F(BindProtoToActivationTest, BindProtoToActivationMapComplex) {
240240
IsOkAndHolds(Optional(IsMapValueOfSize(2))));
241241
}
242242

243+
TEST_F(BindProtoToActivationTest, BindProtoViewToActivation) {
244+
TestAllTypes test_all_types;
245+
test_all_types.set_single_int64(123);
246+
Activation activation;
247+
248+
ASSERT_THAT(
249+
BindProtoViewToActivation(test_all_types, descriptor_pool(),
250+
message_factory(), arena(), &activation),
251+
IsOk());
252+
253+
EXPECT_THAT(activation.FindVariable("single_int64", descriptor_pool(),
254+
message_factory(), arena()),
255+
IsOkAndHolds(Optional(IntValueIs(123))));
256+
}
257+
258+
TEST_F(BindProtoToActivationTest, BindProtoViewToActivationDefault) {
259+
TestAllTypes test_all_types;
260+
test_all_types.set_single_int64(123);
261+
Activation activation;
262+
263+
ASSERT_THAT(
264+
BindProtoViewToActivation(
265+
test_all_types, BindProtoUnsetFieldBehavior::kBindDefaultValue,
266+
descriptor_pool(), message_factory(), arena(), &activation),
267+
IsOk());
268+
269+
EXPECT_THAT(activation.FindVariable("single_int32", descriptor_pool(),
270+
message_factory(), arena()),
271+
IsOkAndHolds(Optional(IntValueIs(-32))));
272+
EXPECT_THAT(activation.FindVariable("single_sint32", descriptor_pool(),
273+
message_factory(), arena()),
274+
IsOkAndHolds(Optional(IntValueIs(0))));
275+
}
276+
243277
} // namespace
244278
} // namespace cel

0 commit comments

Comments
 (0)