Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion common/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -793,7 +793,7 @@ cc_library(
"//eval/internal:cel_value_equal",
"//eval/public:cel_value",
"//eval/public:message_wrapper",
"//eval/public/structs:cel_proto_wrap_util",
"//eval/public/structs:cel_proto_wrap_value_to_message",
"//eval/public/structs:legacy_type_info_apis",
"//eval/public/structs:proto_message_type_adapter",
"//eval/public/structs:trivial_legacy_type_info_internal",
Expand Down
7 changes: 6 additions & 1 deletion common/legacy_value.cc
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@
#include "eval/internal/cel_value_equal.h"
#include "eval/public/cel_value.h"
#include "eval/public/message_wrapper.h"
#include "eval/public/structs/cel_proto_wrap_util.h"
#include "eval/public/structs/cel_proto_wrap_value_to_message.h"
#include "eval/public/structs/legacy_type_info_apis.h"
#include "eval/public/structs/proto_message_type_adapter.h"
#include "eval/public/structs/trivial_legacy_type_info_internal.h"
Expand Down Expand Up @@ -260,6 +260,11 @@ CelValue LegacyTrivialStructValue(google::protobuf::Arena* absl_nonnull arena,
}
if (auto parsed_message_value = value.AsParsedMessage();
parsed_message_value) {
if (interop_internal::IsUnsafeParsedMessageValue(*parsed_message_value)) {
return CelValue::CreateMessageWrapper(
AsMessageWrapper(cel::to_address(*parsed_message_value),
&GetGenericProtoTypeInfoInstance()));
}
auto maybe_cloned = parsed_message_value->Clone(arena);
return CelValue::CreateMessageWrapper(MessageWrapper(
cel::to_address(maybe_cloned), &GetGenericProtoTypeInfoInstance()));
Expand Down
4 changes: 4 additions & 0 deletions common/legacy_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,10 @@ class MessageFactory;

namespace cel::interop_internal {

inline bool IsUnsafeParsedMessageValue(const cel::ParsedMessageValue& value) {
return value.is_unsafe();
}

// Returns the underlying `google::protobuf::Message` of a `cel::Value` if it is a legacy
// message with the default type info, or `nullptr` otherwise.
const google::protobuf::Message* absl_nullable GetLegacyMessage(const Value& value);
Expand Down
56 changes: 36 additions & 20 deletions common/values/legacy_map_value.cc
Original file line number Diff line number Diff line change
Expand Up @@ -218,21 +218,33 @@ class LegacyParsedMapFieldMapValue final
if (arena == nullptr) {
arena = arena_;
}
if (auto status =
google::api::expr::runtime::CelValue::CheckMapKeyType(key);
!status.ok()) {
status.IgnoreError();
return std::nullopt;
}
Value modern_key;
if (ABSL_PREDICT_FALSE(!ModernValue(arena, key, modern_key).ok())) {
// Legacy to modern should succeed for a valid CelValue.
return std::nullopt;
}
Value modern_val;
auto status_or_found =
Find(modern_key, google::protobuf::DescriptorPool::generated_pool(),
google::protobuf::MessageFactory::generated_factory(), arena, &modern_val);
if (!status_or_found.ok() || !*status_or_found) {
// Call custom map Find directly. MapValue normally handles wrapping
// non-ok result to error value types, so emulate that here.
//
// Use the descriptor pool and message factory from the value. This is not
// totally consistent with modern APIs, but this should behave the same as
// the legacy map did.
const google::protobuf::Message* msg = value_.message_;
ABSL_DCHECK(msg->GetDescriptor() != nullptr);
ABSL_DCHECK(msg->GetReflection() != nullptr);

const google::protobuf::DescriptorPool* descriptor_pool =
msg->GetDescriptor()->file()->pool();
google::protobuf::MessageFactory* message_factory =
msg->GetReflection()->GetMessageFactory();
auto found =
Find(modern_key, descriptor_pool, message_factory, arena, &modern_val);
if (!found.ok()) {
return google::api::expr::runtime::CreateErrorValue(arena,
found.status());
}
if (!(*found) && !modern_val.IsError()) {
return std::nullopt;
}
return UnsafeLegacyValue(modern_val, /*stable=*/false, arena);
Expand Down Expand Up @@ -401,21 +413,25 @@ class LegacyParsedJsonMapValue final
if (arena == nullptr) {
arena = arena_;
}
if (auto status =
google::api::expr::runtime::CelValue::CheckMapKeyType(key);
!status.ok()) {
status.IgnoreError();
return std::nullopt;
}
Value modern_key;
if (ABSL_PREDICT_FALSE(!ModernValue(arena, key, modern_key).ok())) {
// Legacy to modern should succeed for a valid CelValue.
return std::nullopt;
}
Value modern_val;
auto status_or_found = value_.Find(
modern_key, google::protobuf::DescriptorPool::generated_pool(),
google::protobuf::MessageFactory::generated_factory(), arena, &modern_val);
if (!status_or_found.ok() || !*status_or_found) {
// Call custom map Find directly. MapValue normally handles wrapping
// non-ok result to error value types, so emulate that here.
//
// We know that the descriptor pool and message factory aren't needed here,
// so fine to use generated.
auto found =
Find(modern_key, google::protobuf::DescriptorPool::generated_pool(),
google::protobuf::MessageFactory::generated_factory(), arena, &modern_val);
if (!found.ok()) {
return google::api::expr::runtime::CreateErrorValue(arena,
found.status());
}
if (!(*found) && !modern_val.IsError()) {
return std::nullopt;
}
return UnsafeLegacyValue(modern_val, /*stable=*/false, arena);
Expand Down
12 changes: 12 additions & 0 deletions common/values/legacy_struct_value_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -190,6 +190,18 @@ TEST_F(LegacyStructValueTest, MapFieldKeyTypeValidation) {
CelValue str_key = CelValue::CreateString(&str_key_val);
auto invalid_has_res = cel_map->Has(str_key);
EXPECT_THAT(invalid_has_res, StatusIs(absl::StatusCode::kInvalidArgument));

auto invalid_get_res = cel_map->Get(arena(), str_key);
ASSERT_TRUE(invalid_get_res.has_value());
ASSERT_TRUE(invalid_get_res->IsError());
EXPECT_THAT(*invalid_get_res->ErrorOrDie(),
StatusIs(absl::StatusCode::kInvalidArgument));

auto invalid_subscript_res = (*cel_map)[str_key];
ASSERT_TRUE(invalid_subscript_res.has_value());
ASSERT_TRUE(invalid_subscript_res->IsError());
EXPECT_THAT(*invalid_subscript_res->ErrorOrDie(),
StatusIs(absl::StatusCode::kInvalidArgument));
}

TEST_F(LegacyStructValueTest, JsonStructAccess) {
Expand Down
5 changes: 5 additions & 0 deletions common/values/parsed_map_field_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,10 @@ class ValueIterator;
class ListValue;
class ParsedJsonMapValue;

namespace common_internal {
class LegacyParsedMapFieldMapValue;
} // namespace common_internal

// ParsedMapFieldValue is a MapValue over a map field of a parsed protocol
// buffer message.
class ParsedMapFieldValue final
Expand Down Expand Up @@ -192,6 +196,7 @@ class ParsedMapFieldValue final
friend class ParsedJsonMapValue;
friend class common_internal::ValueMixin<ParsedMapFieldValue>;
friend class common_internal::MapValueMixin<ParsedMapFieldValue>;
friend class common_internal::LegacyParsedMapFieldMapValue;
friend ParsedMapFieldValue UnsafeParsedMapFieldValue(
const google::protobuf::Message* absl_nonnull message,
const google::protobuf::FieldDescriptor* absl_nonnull field);
Expand Down
6 changes: 6 additions & 0 deletions common/values/parsed_message_value.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,10 @@

namespace cel {

namespace interop_internal {
bool IsUnsafeParsedMessageValue(const ParsedMessageValue& value);
}

class MessageValue;
class StructValue;
class Value;
Expand Down Expand Up @@ -189,6 +193,8 @@ class ParsedMessageValue final
friend class common_internal::StructValueMixin<ParsedMessageValue>;
friend ParsedMessageValue UnsafeParsedMessageValue(
const google::protobuf::Message* absl_nonnull value);
friend bool interop_internal::IsUnsafeParsedMessageValue(
const ParsedMessageValue& value);

explicit ParsedMessageValue(
const google::protobuf::Message* absl_nonnull value ABSL_ATTRIBUTE_LIFETIME_BOUND)
Expand Down
3 changes: 1 addition & 2 deletions eval/internal/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,10 @@ cc_test(
"//eval/public/structs:trivial_legacy_type_info",
"//eval/testutil:test_message_cc_proto",
"//internal:testing",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/log:absl_check",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:span",
"@com_google_absl//absl/types:variant",
"@com_google_googleapis//google/rpc/context:attribute_context_cc_proto",
"@com_google_protobuf//:any_cc_proto",
"@com_google_protobuf//:protobuf",
Expand Down
13 changes: 8 additions & 5 deletions eval/internal/cel_value_equal_test.cc
Original file line number Diff line number Diff line change
Expand Up @@ -18,20 +18,21 @@
#include <cstdint>
#include <limits>
#include <memory>
#include <optional>
#include <string>
#include <tuple>
#include <utility>
#include <variant>
#include <vector>

#include "google/protobuf/any.pb.h"
#include "google/rpc/context/attribute_context.pb.h"
#include "google/protobuf/descriptor.pb.h"
#include "absl/status/statusor.h"
#include "absl/log/absl_check.h"
#include "absl/strings/str_cat.h"
#include "absl/strings/string_view.h"
#include "absl/time/time.h"
#include "absl/types/span.h"
#include "absl/types/variant.h"
#include "eval/public/cel_value.h"
#include "eval/public/containers/container_backed_list_impl.h"
#include "eval/public/containers/container_backed_map_impl.h"
Expand Down Expand Up @@ -131,6 +132,8 @@ const std::vector<CelValue>& ValueExamples1() {
result->push_back(CelValue::CreateMap(&CelMapExample1()));
result->push_back(CelValue::CreateCelTypeView("type"));

ABSL_CHECK_EQ(arena.SpaceUsed(), 0) << "Arena should not be used.";

return result.release();
}();
return *examples;
Expand Down Expand Up @@ -185,7 +188,7 @@ std::string CelValueEqualTestName(
}

TEST_P(CelValueEqualImplTypesTest, Basic) {
absl::optional<bool> result = CelValueEqualImpl(lhs(), rhs());
std::optional<bool> result = CelValueEqualImpl(lhs(), rhs());

if (lhs().IsNull() || rhs().IsNull()) {
if (lhs().IsNull() && rhs().IsNull()) {
Expand Down Expand Up @@ -267,7 +270,7 @@ const std::vector<NumericInequalityTestCase>& NumericValuesNotEqualExample() {
using NumericInequalityTest = testing::TestWithParam<NumericInequalityTestCase>;
TEST_P(NumericInequalityTest, NumericValues) {
NumericInequalityTestCase test_case = GetParam();
absl::optional<bool> result = CelValueEqualImpl(test_case.a, test_case.b);
std::optional<bool> result = CelValueEqualImpl(test_case.a, test_case.b);
EXPECT_TRUE(result.has_value());
EXPECT_EQ(*result, false);
}
Expand All @@ -280,7 +283,7 @@ INSTANTIATE_TEST_SUITE_P(
});

TEST(CelValueEqualImplTest, LossyNumericEquality) {
absl::optional<bool> result = CelValueEqualImpl(
std::optional<bool> result = CelValueEqualImpl(
CelValue::CreateDouble(
static_cast<double>(std::numeric_limits<int64_t>::max()) - 1),
CelValue::CreateInt64(std::numeric_limits<int64_t>::max()));
Expand Down
77 changes: 67 additions & 10 deletions eval/public/structs/BUILD
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,19 @@ cc_library(
"cel_proto_wrapper.h",
],
deps = [
":cel_proto_wrap_util",
":cel_proto_wrap_value_to_message",
":proto_message_type_adapter",
":trivial_legacy_type_info_internal",
"//common:value",
"//eval/public:cel_value",
"//eval/public:message_wrapper",
"//internal:proto_time_encoding",
"@com_google_absl//absl/types:optional",
"@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:absl_log",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_protobuf//:duration_cc_proto",
"@com_google_protobuf//:protobuf",
"@com_google_protobuf//:timestamp_cc_proto",
Expand Down Expand Up @@ -62,16 +69,13 @@ cc_library(
deps = [
":protobuf_value_factory",
"//eval/public:cel_value",
"//internal:overflow",
"//internal:proto_time_encoding",
"//internal:status_macros",
"//internal:time",
"//internal:well_known_types",
"@com_google_absl//absl/base:core_headers",
"@com_google_absl//absl/base:nullability",
"@com_google_absl//absl/functional:overload",
"@com_google_absl//absl/log:absl_check",
"@com_google_absl//absl/log:absl_log",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
Expand All @@ -97,19 +101,70 @@ cc_test(
],
deps = [
":cel_proto_wrap_util",
":protobuf_value_factory",
":trivial_legacy_type_info",
"//eval/public:cel_value",
"//eval/public:message_wrapper",
"//eval/public/containers:container_backed_list_impl",
"//eval/public/containers:container_backed_map_impl",
"//eval/testutil:test_message_cc_proto",
"//internal:proto_time_encoding",
"//internal:testing",
"//testutil:util",
"@com_google_absl//absl/status",
"@com_google_protobuf//:any_cc_proto",
"@com_google_protobuf//:duration_cc_proto",
"@com_google_protobuf//:empty_cc_proto",
"@com_google_protobuf//:field_mask_cc_proto",
"@com_google_protobuf//:protobuf",
"@com_google_protobuf//:struct_cc_proto",
"@com_google_protobuf//:wrappers_cc_proto",
],
)

cc_library(
name = "cel_proto_wrap_value_to_message",
srcs = [
"cel_proto_wrap_value_to_message.cc",
],
hdrs = [
"cel_proto_wrap_value_to_message.h",
],
deps = [
"//eval/public:cel_value",
"//internal:overflow",
"//internal:proto_time_encoding",
"//internal:status_macros",
"//internal:time",
"//internal:well_known_types",
"@com_google_absl//absl/log:absl_log",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:statusor",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/strings:cord",
"@com_google_absl//absl/time",
"@com_google_protobuf//:any_cc_proto",
"@com_google_protobuf//:duration_cc_proto",
"@com_google_protobuf//:protobuf",
"@com_google_protobuf//:struct_cc_proto",
"@com_google_protobuf//:timestamp_cc_proto",
"@com_google_protobuf//:wrappers_cc_proto",
],
)

cc_test(
name = "cel_proto_wrap_value_to_message_test",
size = "small",
srcs = [
"cel_proto_wrap_value_to_message_test.cc",
],
deps = [
":cel_proto_wrap_value_to_message",
":trivial_legacy_type_info",
"//eval/public:cel_value",
"//eval/public/containers:container_backed_list_impl",
"//eval/public/containers:container_backed_map_impl",
"//eval/testutil:test_message_cc_proto",
"//internal:testing",
"//testutil:util",
"@com_google_absl//absl/base:no_destructor",
"@com_google_absl//absl/status",
"@com_google_absl//absl/status:status_matchers",
"@com_google_absl//absl/strings",
"@com_google_absl//absl/time",
"@com_google_absl//absl/types:span",
Expand All @@ -119,6 +174,7 @@ cc_test(
"@com_google_protobuf//:field_mask_cc_proto",
"@com_google_protobuf//:protobuf",
"@com_google_protobuf//:struct_cc_proto",
"@com_google_protobuf//:timestamp_cc_proto",
"@com_google_protobuf//:wrappers_cc_proto",
],
)
Expand All @@ -133,6 +189,7 @@ cc_library(
],
deps = [
":cel_proto_wrap_util",
":cel_proto_wrap_value_to_message",
":protobuf_value_factory",
"//eval/public:cel_options",
"//eval/public:cel_value",
Expand Down
Loading
Loading