From d65ec5423090ce9fde2405cf474b8fbc3ccdecf3 Mon Sep 17 00:00:00 2001 From: Justin King Date: Mon, 27 Nov 2023 16:36:39 -0800 Subject: [PATCH] `UnknownValue` and `UnknownValueView` PiperOrigin-RevId: 585794277 --- common/value.h | 1 + common/values/unknown_value.h | 110 ++++++++++++++++++++++++ common/values/unknown_value_test.cc | 124 ++++++++++++++++++++++++++++ common/values/values.h | 13 ++- 4 files changed, 244 insertions(+), 4 deletions(-) create mode 100644 common/values/unknown_value.h create mode 100644 common/values/unknown_value_test.cc diff --git a/common/value.h b/common/value.h index 2e8ade09c..75eb2581d 100644 --- a/common/value.h +++ b/common/value.h @@ -44,6 +44,7 @@ #include "common/values/timestamp_value.h" // IWYU pragma: export #include "common/values/type_value.h" // IWYU pragma: export #include "common/values/uint_value.h" // IWYU pragma: export +#include "common/values/unknown_value.h" // IWYU pragma: export #include "common/values/values.h" namespace cel { diff --git a/common/values/unknown_value.h b/common/values/unknown_value.h new file mode 100644 index 000000000..0a60bab58 --- /dev/null +++ b/common/values/unknown_value.h @@ -0,0 +1,110 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +// IWYU pragma: private, include "common/value.h" +// IWYU pragma: friend "common/value.h" + +// TODO(uncreated-issue/61): finish implementing this is just a placeholder for now + +#ifndef THIRD_PARTY_CEL_CPP_COMMON_VALUES_UNKNOWN_VALUE_H_ +#define THIRD_PARTY_CEL_CPP_COMMON_VALUES_UNKNOWN_VALUE_H_ + +#include +#include + +#include "absl/base/attributes.h" +#include "common/type.h" +#include "common/value_kind.h" + +namespace cel { + +class UnknownValue; +class UnknownValueView; + +// `UnknownValue` represents values of the primitive `duration` type. +class UnknownValue final { + public: + using view_alternative_type = UnknownValueView; + + static constexpr ValueKind kKind = ValueKind::kUnknown; + + explicit UnknownValue(UnknownValueView) noexcept; + + UnknownValue() = default; + UnknownValue(const UnknownValue&) = default; + UnknownValue(UnknownValue&&) = default; + UnknownValue& operator=(const UnknownValue&) = default; + UnknownValue& operator=(UnknownValue&&) = default; + + constexpr ValueKind kind() const { return kKind; } + + UnknownTypeView type() const { return UnknownTypeView(); } + + std::string DebugString() const { return ""; } + + void swap(UnknownValue& other) noexcept {} + + private: + friend class UnknownValueView; +}; + +inline void swap(UnknownValue& lhs, UnknownValue& rhs) noexcept { + lhs.swap(rhs); +} + +inline std::ostream& operator<<(std::ostream& out, const UnknownValue& value) { + return out << value.DebugString(); +} + +class UnknownValueView final { + public: + using alternative_type = UnknownValue; + + static constexpr ValueKind kKind = UnknownValue::kKind; + + // NOLINTNEXTLINE(google-explicit-constructor) + UnknownValueView(const UnknownValue& value ABSL_ATTRIBUTE_LIFETIME_BOUND + ABSL_ATTRIBUTE_UNUSED) noexcept {} + + UnknownValueView() = default; + UnknownValueView(const UnknownValueView&) = default; + UnknownValueView(UnknownValueView&&) = default; + UnknownValueView& operator=(const UnknownValueView&) = default; + UnknownValueView& operator=(UnknownValueView&&) = default; + + constexpr ValueKind kind() const { return kKind; } + + UnknownTypeView type() const { return UnknownTypeView(); } + + std::string DebugString() const { return ""; } + + void swap(UnknownValueView& other) noexcept {} + + private: + friend class UnknownValue; +}; + +inline void swap(UnknownValueView& lhs, UnknownValueView& rhs) noexcept { + lhs.swap(rhs); +} + +inline std::ostream& operator<<(std::ostream& out, UnknownValueView value) { + return out << value.DebugString(); +} + +inline UnknownValue::UnknownValue(UnknownValueView) noexcept {} + +} // namespace cel + +#endif // THIRD_PARTY_CEL_CPP_COMMON_VALUES_UNKNOWN_VALUE_H_ diff --git a/common/values/unknown_value_test.cc b/common/values/unknown_value_test.cc new file mode 100644 index 000000000..39ec36128 --- /dev/null +++ b/common/values/unknown_value_test.cc @@ -0,0 +1,124 @@ +// Copyright 2023 Google LLC +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// https://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +#include + +#include "absl/types/optional.h" +#include "common/casting.h" +#include "common/native_type.h" +#include "common/type.h" +#include "common/value.h" +#include "internal/testing.h" + +namespace cel { +namespace { + +using testing::An; +using testing::Ne; + +TEST(UnknownValue, Kind) { + EXPECT_EQ(UnknownValue().kind(), UnknownValue::kKind); + EXPECT_EQ(Value(UnknownValue()).kind(), UnknownValue::kKind); +} + +TEST(UnknownValue, Type) { + EXPECT_EQ(UnknownValue().type(), UnknownType()); + EXPECT_EQ(Value(UnknownValue()).type(), UnknownType()); +} + +TEST(UnknownValue, DebugString) { + { + std::ostringstream out; + out << UnknownValue(); + EXPECT_EQ(out.str(), ""); + } + { + std::ostringstream out; + out << Value(UnknownValue()); + EXPECT_EQ(out.str(), ""); + } +} + +TEST(UnknownValue, NativeTypeId) { + EXPECT_EQ(NativeTypeId::Of(UnknownValue()), + NativeTypeId::For()); + EXPECT_EQ(NativeTypeId::Of(Value(UnknownValue())), + NativeTypeId::For()); +} + +TEST(UnknownValue, InstanceOf) { + EXPECT_TRUE(InstanceOf(UnknownValue())); + EXPECT_TRUE(InstanceOf(Value(UnknownValue()))); +} + +TEST(UnknownValue, Cast) { + EXPECT_THAT(Cast(UnknownValue()), An()); + EXPECT_THAT(Cast(Value(UnknownValue())), An()); +} + +TEST(UnknownValue, As) { + EXPECT_THAT(As(UnknownValue()), Ne(absl::nullopt)); + EXPECT_THAT(As(Value(UnknownValue())), Ne(absl::nullopt)); +} + +TEST(UnknownValueView, Kind) { + EXPECT_EQ(UnknownValueView().kind(), UnknownValueView::kKind); + EXPECT_EQ(ValueView(UnknownValueView()).kind(), UnknownValueView::kKind); +} + +TEST(UnknownValueView, Type) { + EXPECT_EQ(UnknownValueView().type(), UnknownType()); + EXPECT_EQ(ValueView(UnknownValueView()).type(), UnknownType()); +} + +TEST(UnknownValueView, DebugString) { + { + std::ostringstream out; + out << UnknownValueView(); + EXPECT_EQ(out.str(), ""); + } + { + std::ostringstream out; + out << ValueView(UnknownValueView()); + EXPECT_EQ(out.str(), ""); + } +} + +TEST(UnknownValueView, NativeTypeId) { + EXPECT_EQ(NativeTypeId::Of(UnknownValueView()), + NativeTypeId::For()); + EXPECT_EQ(NativeTypeId::Of(ValueView(UnknownValueView())), + NativeTypeId::For()); +} + +TEST(UnknownValueView, InstanceOf) { + EXPECT_TRUE(InstanceOf(UnknownValueView())); + EXPECT_TRUE(InstanceOf(ValueView(UnknownValueView()))); +} + +TEST(UnknownValueView, Cast) { + EXPECT_THAT(Cast(UnknownValueView()), + An()); + EXPECT_THAT(Cast(ValueView(UnknownValueView())), + An()); +} + +TEST(UnknownValueView, As) { + EXPECT_THAT(As(UnknownValueView()), Ne(absl::nullopt)); + EXPECT_THAT(As(ValueView(UnknownValueView())), + Ne(absl::nullopt)); +} + +} // namespace +} // namespace cel diff --git a/common/values/values.h b/common/values/values.h index bd592e889..f4664c428 100644 --- a/common/values/values.h +++ b/common/values/values.h @@ -38,6 +38,7 @@ class StringValue; class TimestampValue; class TypeValue; class UintValue; +class UnknownValue; class ValueView; class BoolValueView; @@ -52,6 +53,7 @@ class StringValueView; class TimestampValueView; class TypeValueView; class UintValueView; +class UnknownValueView; namespace common_internal { @@ -72,7 +74,8 @@ struct IsValueAlternative std::is_same, std::is_same, std::is_same, std::is_same, std::is_same, std::is_same, - std::is_same, std::is_same>> {}; + std::is_same, std::is_same, + std::is_same>> {}; template inline constexpr bool IsValueAlternativeV = IsValueAlternative::value; @@ -85,7 +88,8 @@ using ValueVariant = absl::variant< absl::monostate, #endif BoolValue, BytesValue, DoubleValue, DurationValue, EnumValue, ErrorValue, - IntValue, NullValue, StringValue, TimestampValue, TypeValue, UintValue>; + IntValue, NullValue, StringValue, TimestampValue, TypeValue, UintValue, + UnknownValue>; template struct IsValueViewAlternative @@ -95,7 +99,8 @@ struct IsValueViewAlternative std::is_same, std::is_same, std::is_same, std::is_same, std::is_same, std::is_same, - std::is_same, std::is_same>> {}; + std::is_same, std::is_same, + std::is_same>> {}; template inline constexpr bool IsValueViewAlternativeV = @@ -110,7 +115,7 @@ using ValueViewVariant = absl::variant< #endif BoolValueView, BytesValueView, DoubleValueView, DurationValueView, EnumValueView, ErrorValueView, IntValueView, NullValueView, StringValueView, - TimestampValueView, TypeValueView, UintValueView>; + TimestampValueView, TypeValueView, UintValueView, UnknownValueView>; // Get the base type alternative for the given alternative or interface. The // base type alternative is the type stored in the `ValueVariant`.