diff --git a/common/BUILD b/common/BUILD index 0140aec4d..edd682d27 100644 --- a/common/BUILD +++ b/common/BUILD @@ -279,38 +279,14 @@ cc_library( cc_library( name = "json", - srcs = ["json.cc"], hdrs = ["json.h"], deps = [ - ":any", - "//internal:copy_on_write", - "//internal:proto_wire", - "//internal:status_macros", "@com_google_absl//absl/base:core_headers", - "@com_google_absl//absl/base:no_destructor", "@com_google_absl//absl/base:nullability", - "@com_google_absl//absl/container:flat_hash_map", - "@com_google_absl//absl/functional:overload", - "@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/types:variant", "@com_google_protobuf//:protobuf", ], ) -cc_test( - name = "json_test", - srcs = ["json_test.cc"], - deps = [ - ":json", - "//internal:testing", - "@com_google_absl//absl/hash:hash_testing", - "@com_google_absl//absl/strings", - ], -) - cc_library( name = "kind", srcs = ["kind.cc"], diff --git a/common/json.cc b/common/json.cc deleted file mode 100644 index f596aeb3e..000000000 --- a/common/json.cc +++ /dev/null @@ -1,402 +0,0 @@ -// 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 "common/json.h" - -#include -#include -#include - -#include "absl/base/no_destructor.h" -#include "absl/functional/overload.h" -#include "absl/status/status.h" -#include "absl/status/statusor.h" -#include "absl/strings/cord.h" -#include "absl/strings/escaping.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "absl/types/variant.h" -#include "common/any.h" -#include "internal/copy_on_write.h" -#include "internal/proto_wire.h" -#include "internal/status_macros.h" - -namespace cel { - -internal::CopyOnWrite JsonArray::Empty() { - static const absl::NoDestructor> empty; - return *empty; -} - -internal::CopyOnWrite JsonObject::Empty() { - static const absl::NoDestructor> empty; - return *empty; -} - -Json JsonInt(int64_t value) { - if (value < kJsonMinInt || value > kJsonMaxInt) { - return JsonString(absl::StrCat(value)); - } - return Json(static_cast(value)); -} - -Json JsonUint(uint64_t value) { - if (value > kJsonMaxUint) { - return JsonString(absl::StrCat(value)); - } - return Json(static_cast(value)); -} - -Json JsonBytes(absl::string_view value) { - return JsonString(absl::Base64Escape(value)); -} - -Json JsonBytes(const absl::Cord& value) { - if (auto flat = value.TryFlat(); flat.has_value()) { - return JsonBytes(*flat); - } - return JsonBytes(absl::string_view(static_cast(value))); -} - -bool JsonArrayBuilder::empty() const { return impl_.get().empty(); } - -JsonArray JsonArrayBuilder::Build() && { return JsonArray(std::move(impl_)); } - -JsonArrayBuilder::JsonArrayBuilder(JsonArray array) - : impl_(std::move(array.impl_)) {} - -JsonObjectBuilder::JsonObjectBuilder(JsonObject object) - : impl_(std::move(object.impl_)) {} - -void JsonObjectBuilder::insert(std::initializer_list il) { - impl_.mutable_get().insert(il); -} - -JsonArrayBuilder::size_type JsonArrayBuilder::size() const { - return impl_.get().size(); -} - -JsonArrayBuilder::iterator JsonArrayBuilder::begin() { - return impl_.mutable_get().begin(); -} - -JsonArrayBuilder::const_iterator JsonArrayBuilder::begin() const { - return impl_.get().begin(); -} - -JsonArrayBuilder::iterator JsonArrayBuilder::end() { - return impl_.mutable_get().end(); -} - -JsonArrayBuilder::const_iterator JsonArrayBuilder::end() const { - return impl_.get().end(); -} - -JsonArrayBuilder::reverse_iterator JsonArrayBuilder::rbegin() { - return impl_.mutable_get().rbegin(); -} - -JsonArrayBuilder::reverse_iterator JsonArrayBuilder::rend() { - return impl_.mutable_get().rend(); -} - -JsonArrayBuilder::reference JsonArrayBuilder::at(size_type index) { - return impl_.mutable_get().at(index); -} - -JsonArrayBuilder::reference JsonArrayBuilder::operator[](size_type index) { - return (impl_.mutable_get())[index]; -} - -void JsonArrayBuilder::reserve(size_type n) { - if (n != 0) { - impl_.mutable_get().reserve(n); - } -} - -void JsonArrayBuilder::clear() { impl_.mutable_get().clear(); } - -void JsonArrayBuilder::push_back(Json json) { - impl_.mutable_get().push_back(std::move(json)); -} - -void JsonArrayBuilder::pop_back() { impl_.mutable_get().pop_back(); } - -JsonArrayBuilder::operator JsonArray() && { return std::move(*this).Build(); } - -bool JsonArray::empty() const { return impl_.get().empty(); } - -JsonArray::JsonArray(internal::CopyOnWrite impl) - : impl_(std::move(impl)) { - if (impl_.get().empty()) { - impl_ = Empty(); - } -} - -JsonArray::size_type JsonArray::size() const { return impl_.get().size(); } - -JsonArray::const_iterator JsonArray::begin() const { - return impl_.get().begin(); -} - -JsonArray::const_iterator JsonArray::cbegin() const { return begin(); } - -JsonArray::const_iterator JsonArray::end() const { return impl_.get().end(); } - -JsonArray::const_iterator JsonArray::cend() const { return begin(); } - -JsonArray::const_reverse_iterator JsonArray::rbegin() const { - return impl_.get().rbegin(); -} - -JsonArray::const_reverse_iterator JsonArray::crbegin() const { - return impl_.get().crbegin(); -} - -JsonArray::const_reverse_iterator JsonArray::rend() const { - return impl_.get().rend(); -} - -JsonArray::const_reverse_iterator JsonArray::crend() const { - return impl_.get().crend(); -} - -JsonArray::const_reference JsonArray::at(size_type index) const { - return impl_.get().at(index); -} - -JsonArray::const_reference JsonArray::operator[](size_type index) const { - return (impl_.get())[index]; -} - -bool operator==(const JsonArray& lhs, const JsonArray& rhs) { - return lhs.impl_.get() == rhs.impl_.get(); -} - -bool operator!=(const JsonArray& lhs, const JsonArray& rhs) { - return lhs.impl_.get() != rhs.impl_.get(); -} - -JsonObjectBuilder::operator JsonObject() && { return std::move(*this).Build(); } - -bool JsonObjectBuilder::empty() const { return impl_.get().empty(); } - -JsonObjectBuilder::size_type JsonObjectBuilder::size() const { - return impl_.get().size(); -} - -JsonObjectBuilder::iterator JsonObjectBuilder::begin() { - return impl_.mutable_get().begin(); -} - -JsonObjectBuilder::const_iterator JsonObjectBuilder::begin() const { - return impl_.get().begin(); -} - -JsonObjectBuilder::iterator JsonObjectBuilder::end() { - return impl_.mutable_get().end(); -} - -JsonObjectBuilder::const_iterator JsonObjectBuilder::end() const { - return impl_.get().end(); -} - -void JsonObjectBuilder::clear() { impl_.mutable_get().clear(); } - -JsonObject JsonObjectBuilder::Build() && { - return JsonObject(std::move(impl_)); -} - -void JsonObjectBuilder::erase(const_iterator pos) { - impl_.mutable_get().erase(std::move(pos)); -} - -void JsonObjectBuilder::reserve(size_type n) { - if (n != 0) { - impl_.mutable_get().reserve(n); - } -} - -JsonObject MakeJsonObject( - std::initializer_list> il) { - JsonObjectBuilder builder; - builder.reserve(il.size()); - for (const auto& entry : il) { - builder.insert(entry); - } - return std::move(builder).Build(); -} - -JsonObject::JsonObject(internal::CopyOnWrite impl) - : impl_(std::move(impl)) { - if (impl_.get().empty()) { - impl_ = Empty(); - } -} - -bool JsonObject::empty() const { return impl_.get().empty(); } - -JsonObject::size_type JsonObject::size() const { return impl_.get().size(); } - -JsonObject::const_iterator JsonObject::begin() const { - return impl_.get().begin(); -} - -JsonObject::const_iterator JsonObject::cbegin() const { return begin(); } - -JsonObject::const_iterator JsonObject::end() const { return impl_.get().end(); } - -JsonObject::const_iterator JsonObject::cend() const { return end(); } - -bool operator==(const JsonObject& lhs, const JsonObject& rhs) { - return lhs.impl_.get() == rhs.impl_.get(); -} - -bool operator!=(const JsonObject& lhs, const JsonObject& rhs) { - return lhs.impl_.get() != rhs.impl_.get(); -} - -namespace { - -using internal::ProtoWireEncoder; -using internal::ProtoWireTag; -using internal::ProtoWireType; - -inline constexpr absl::string_view kJsonTypeName = "google.protobuf.Value"; -inline constexpr absl::string_view kJsonArrayTypeName = - "google.protobuf.ListValue"; -inline constexpr absl::string_view kJsonObjectTypeName = - "google.protobuf.Struct"; - -inline constexpr ProtoWireTag kValueNullValueFieldTag = - ProtoWireTag(1, ProtoWireType::kVarint); -inline constexpr ProtoWireTag kValueBoolValueFieldTag = - ProtoWireTag(4, ProtoWireType::kVarint); -inline constexpr ProtoWireTag kValueNumberValueFieldTag = - ProtoWireTag(2, ProtoWireType::kFixed64); -inline constexpr ProtoWireTag kValueStringValueFieldTag = - ProtoWireTag(3, ProtoWireType::kLengthDelimited); -inline constexpr ProtoWireTag kValueListValueFieldTag = - ProtoWireTag(6, ProtoWireType::kLengthDelimited); -inline constexpr ProtoWireTag kValueStructValueFieldTag = - ProtoWireTag(5, ProtoWireType::kLengthDelimited); - -inline constexpr ProtoWireTag kListValueValuesFieldTag = - ProtoWireTag(1, ProtoWireType::kLengthDelimited); - -inline constexpr ProtoWireTag kStructFieldsEntryKeyFieldTag = - ProtoWireTag(1, ProtoWireType::kLengthDelimited); -inline constexpr ProtoWireTag kStructFieldsEntryValueFieldTag = - ProtoWireTag(2, ProtoWireType::kLengthDelimited); - -absl::StatusOr JsonObjectEntryToAnyValue(const absl::Cord& key, - const Json& value) { - absl::Cord data; - ProtoWireEncoder encoder("google.protobuf.Struct.FieldsEntry", data); - absl::Cord subdata; - CEL_RETURN_IF_ERROR(JsonToAnyValue(value, subdata)); - CEL_RETURN_IF_ERROR(encoder.WriteTag(kStructFieldsEntryKeyFieldTag)); - CEL_RETURN_IF_ERROR(encoder.WriteLengthDelimited(std::move(key))); - CEL_RETURN_IF_ERROR(encoder.WriteTag(kStructFieldsEntryValueFieldTag)); - CEL_RETURN_IF_ERROR(encoder.WriteLengthDelimited(std::move(subdata))); - encoder.EnsureFullyEncoded(); - return data; -} - -inline constexpr ProtoWireTag kStructFieldsFieldTag = - ProtoWireTag(1, ProtoWireType::kLengthDelimited); - -} // namespace - -absl::Status JsonToAnyValue(const Json& json, absl::Cord& data) { - ProtoWireEncoder encoder(kJsonTypeName, data); - absl::Status status = absl::visit( - absl::Overload( - [&encoder](JsonNull) -> absl::Status { - CEL_RETURN_IF_ERROR(encoder.WriteTag(kValueNullValueFieldTag)); - return encoder.WriteVarint(0); - }, - [&encoder](JsonBool value) -> absl::Status { - CEL_RETURN_IF_ERROR(encoder.WriteTag(kValueBoolValueFieldTag)); - return encoder.WriteVarint(value); - }, - [&encoder](JsonNumber value) -> absl::Status { - CEL_RETURN_IF_ERROR(encoder.WriteTag(kValueNumberValueFieldTag)); - return encoder.WriteFixed64(value); - }, - [&encoder](const JsonString& value) -> absl::Status { - CEL_RETURN_IF_ERROR(encoder.WriteTag(kValueStringValueFieldTag)); - return encoder.WriteLengthDelimited(value); - }, - [&encoder](const JsonArray& value) -> absl::Status { - absl::Cord subdata; - CEL_RETURN_IF_ERROR(JsonArrayToAnyValue(value, subdata)); - CEL_RETURN_IF_ERROR(encoder.WriteTag(kValueListValueFieldTag)); - return encoder.WriteLengthDelimited(std::move(subdata)); - }, - [&encoder](const JsonObject& value) -> absl::Status { - absl::Cord subdata; - CEL_RETURN_IF_ERROR(JsonObjectToAnyValue(value, subdata)); - CEL_RETURN_IF_ERROR(encoder.WriteTag(kValueStructValueFieldTag)); - return encoder.WriteLengthDelimited(std::move(subdata)); - }), - json); - CEL_RETURN_IF_ERROR(status); - encoder.EnsureFullyEncoded(); - return absl::OkStatus(); -} - -absl::Status JsonArrayToAnyValue(const JsonArray& json, absl::Cord& data) { - ProtoWireEncoder encoder(kJsonArrayTypeName, data); - for (const auto& element : json) { - absl::Cord subdata; - CEL_RETURN_IF_ERROR(JsonToAnyValue(element, subdata)); - CEL_RETURN_IF_ERROR(encoder.WriteTag(kListValueValuesFieldTag)); - CEL_RETURN_IF_ERROR(encoder.WriteLengthDelimited(std::move(subdata))); - } - encoder.EnsureFullyEncoded(); - return absl::OkStatus(); -} - -absl::Status JsonObjectToAnyValue(const JsonObject& json, absl::Cord& data) { - ProtoWireEncoder encoder(kJsonObjectTypeName, data); - for (const auto& entry : json) { - CEL_ASSIGN_OR_RETURN(auto subdata, - JsonObjectEntryToAnyValue(entry.first, entry.second)); - CEL_RETURN_IF_ERROR(encoder.WriteTag(kStructFieldsFieldTag)); - CEL_RETURN_IF_ERROR(encoder.WriteLengthDelimited(std::move(subdata))); - } - encoder.EnsureFullyEncoded(); - return absl::OkStatus(); -} - -absl::StatusOr JsonToAny(const Json& json) { - absl::Cord data; - CEL_RETURN_IF_ERROR(JsonToAnyValue(json, data)); - return MakeAny(MakeTypeUrl(kJsonTypeName), std::move(data)); -} - -absl::StatusOr JsonArrayToAny(const JsonArray& json) { - absl::Cord data; - CEL_RETURN_IF_ERROR(JsonArrayToAnyValue(json, data)); - return MakeAny(MakeTypeUrl(kJsonArrayTypeName), std::move(data)); -} - -absl::StatusOr JsonObjectToAny(const JsonObject& json) { - absl::Cord data; - CEL_RETURN_IF_ERROR(JsonObjectToAnyValue(json, data)); - return MakeAny(MakeTypeUrl(kJsonObjectTypeName), std::move(data)); -} - -} // namespace cel diff --git a/common/json.h b/common/json.h index 5aa5c2bca..1a3c9fe5c 100644 --- a/common/json.h +++ b/common/json.h @@ -16,20 +16,10 @@ #define THIRD_PARTY_CEL_CPP_COMMON_JSON_H_ #include -#include #include -#include -#include "google/protobuf/any.pb.h" #include "absl/base/attributes.h" #include "absl/base/nullability.h" -#include "absl/container/flat_hash_map.h" -#include "absl/status/status.h" -#include "absl/status/statusor.h" -#include "absl/strings/cord.h" -#include "absl/strings/string_view.h" -#include "absl/types/variant.h" -#include "internal/copy_on_write.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/message.h" @@ -46,442 +36,6 @@ inline constexpr int64_t kJsonMinInt = -kJsonMaxInt; // data. inline constexpr uint64_t kJsonMaxUint = (uint64_t{1} << 53) - 1; -// `cel::JsonNull` is a strong type representing a parsed JSON `null`. -struct ABSL_ATTRIBUTE_TRIVIAL_ABI JsonNull final { - explicit JsonNull() = default; -}; - -inline constexpr JsonNull kJsonNull{}; - -constexpr bool operator==(JsonNull, JsonNull) noexcept { return true; } - -constexpr bool operator!=(JsonNull, JsonNull) noexcept { return false; } - -constexpr bool operator<(JsonNull, JsonNull) noexcept { return false; } - -constexpr bool operator<=(JsonNull, JsonNull) noexcept { return true; } - -constexpr bool operator>(JsonNull, JsonNull) noexcept { return false; } - -constexpr bool operator>=(JsonNull, JsonNull) noexcept { return true; } - -template -H AbslHashValue(H state, JsonNull) { - return H::combine(std::move(state), uintptr_t{0}); -} - -// We cannot use type aliases to the containers because that would make `Json` -// a recursive template. So we need to forward declare array and object -// representations as another class. -class ABSL_ATTRIBUTE_TRIVIAL_ABI JsonArray; -class ABSL_ATTRIBUTE_TRIVIAL_ABI JsonObject; -class JsonArrayBuilder; -class JsonObjectBuilder; - -// `cel::JsonBool` is a convenient alias to `bool` for the purpose of -// readability, it represents a parsed JSON `false` or `true`. -using JsonBool = bool; - -// `cel::JsonNumber` is a convenient alias to `double` for the purpose of -// readability, it represents a parsed JSON number. -using JsonNumber = double; - -// `cel::JsonString` is a convenient alias to `absl::Cord` for the purpose of -// readability, it represents a parsed JSON string. -using JsonString = absl::Cord; - -// `cel::Json` is a variant which holds parsed JSON data. It is either -// `cel::JsonNull`, `cel::JsonBool`, `cel::JsonNumber`, `cel::JsonString`, -// `cel::JsonArray,` or `cel::JsonObject`. -using Json = absl::variant; - -// `cel::JsonArray` uses copy-on-write semantics. Whenever a non-const method is -// called, it would have to assume a mutation is occurring potentially -// performing a copy. To avoid this subtly, `cel::JsonArray` is read-only. To -// perform mutations you must use `cel::JsonArrayBuilder`. -class JsonArrayBuilder { - private: - using Container = std::vector; - - public: - using value_type = typename Container::value_type; - using size_type = typename Container::size_type; - using difference_type = typename Container::difference_type; - using reference = typename Container::reference; - using const_reference = typename Container::const_reference; - using pointer = typename Container::pointer; - using const_pointer = typename Container::const_pointer; - using iterator = typename Container::iterator; - using const_iterator = typename Container::const_iterator; - using reverse_iterator = typename Container::reverse_iterator; - using const_reverse_iterator = typename Container::const_reverse_iterator; - - JsonArrayBuilder() = default; - - explicit JsonArrayBuilder(JsonArray array); - - JsonArrayBuilder(const JsonArrayBuilder&) = delete; - JsonArrayBuilder(JsonArrayBuilder&&) = default; - - JsonArrayBuilder& operator=(const JsonArrayBuilder&) = delete; - JsonArrayBuilder& operator=(JsonArrayBuilder&&) = default; - - bool empty() const; - - size_type size() const; - - iterator begin(); - - const_iterator begin() const; - - iterator end(); - - const_iterator end() const; - - reverse_iterator rbegin(); - - reverse_iterator rend(); - - reference at(size_type index); - - reference operator[](size_type index); - - void reserve(size_type n); - - void clear(); - - void push_back(Json json); - - void pop_back(); - - JsonArray Build() &&; - - // NOLINTNEXTLINE(google-explicit-constructor) - operator JsonArray() &&; - - private: - internal::CopyOnWrite impl_; -}; - -// `cel::JsonArray` is a read-only sequence of `cel::Json` elements. -class ABSL_ATTRIBUTE_TRIVIAL_ABI JsonArray final { - private: - using Container = std::vector; - - public: - using value_type = typename Container::value_type; - using size_type = typename Container::size_type; - using difference_type = typename Container::difference_type; - using reference = typename Container::const_reference; - using const_reference = typename Container::const_reference; - using pointer = typename Container::const_pointer; - using const_pointer = typename Container::const_pointer; - using iterator = typename Container::const_iterator; - using const_iterator = typename Container::const_iterator; - using reverse_iterator = typename Container::const_reverse_iterator; - using const_reverse_iterator = typename Container::const_reverse_iterator; - - JsonArray() : impl_(Empty()) {} - - JsonArray(const JsonArray&) = default; - JsonArray(JsonArray&&) = default; - - JsonArray& operator=(const JsonArray&) = default; - JsonArray& operator=(JsonArray&&) = default; - - bool empty() const; - - size_type size() const; - - const_iterator begin() const; - - const_iterator cbegin() const; - - const_iterator end() const; - - const_iterator cend() const; - - const_reverse_iterator rbegin() const; - - const_reverse_iterator crbegin() const; - - const_reverse_iterator rend() const; - - const_reverse_iterator crend() const; - - const_reference at(size_type index) const; - - const_reference operator[](size_type index) const; - - friend bool operator==(const JsonArray& lhs, const JsonArray& rhs); - - friend bool operator!=(const JsonArray& lhs, const JsonArray& rhs); - - template - friend H AbslHashValue(H state, const JsonArray& json_array); - - private: - friend class JsonArrayBuilder; - - static internal::CopyOnWrite Empty(); - - explicit JsonArray(internal::CopyOnWrite impl); - - internal::CopyOnWrite impl_; -}; - -// `cel::JsonObject` uses copy-on-write semantics. Whenever a non-const method -// is called, it would have to assume a mutation is occurring potentially -// performing a copy. To avoid this subtly, `cel::JsonObject` is read-only. To -// perform mutations you must use `cel::JsonObjectBuilder`. -class JsonObjectBuilder final { - private: - using Container = absl::flat_hash_map; - - public: - using key_type = typename Container::key_type; - using mapped_type = typename Container::mapped_type; - using value_type = typename Container::value_type; - using size_type = typename Container::size_type; - using difference_type = typename Container::difference_type; - using reference = typename Container::reference; - using const_reference = typename Container::const_reference; - using pointer = typename Container::pointer; - using const_pointer = typename Container::const_pointer; - using iterator = typename Container::iterator; - using const_iterator = typename Container::const_iterator; - - JsonObjectBuilder() = default; - - explicit JsonObjectBuilder(JsonObject object); - - JsonObjectBuilder(const JsonObjectBuilder&) = delete; - JsonObjectBuilder(JsonObjectBuilder&&) = default; - - JsonObjectBuilder& operator=(const JsonObjectBuilder&) = delete; - JsonObjectBuilder& operator=(JsonObjectBuilder&&) = default; - - bool empty() const; - - size_type size() const; - - iterator begin(); - - const_iterator begin() const; - - iterator end(); - - const_iterator end() const; - - void clear(); - - template - iterator find(const K& key); - - template - bool contains(const K& key); - - template - std::pair insert(P&& value); - - template - void insert(InputIterator first, InputIterator last); - - void insert(std::initializer_list il); - - template - std::pair insert_or_assign(const key_type& k, M&& obj); - - template - std::pair insert_or_assign(key_type&& k, M&& obj); - - template - std::pair try_emplace(const key_type& key, Args&&... args); - - template - std::pair try_emplace(key_type&& key, Args&&... args); - - template - std::pair emplace(Args&&... args); - - template - size_type erase(const K& k); - - void erase(const_iterator pos); - - iterator erase(const_iterator first, const_iterator last); - - void reserve(size_type n); - - JsonObject Build() &&; - - // NOLINTNEXTLINE(google-explicit-constructor) - operator JsonObject() &&; - - private: - internal::CopyOnWrite impl_; -}; - -// `cel::JsonObject` is a read-only mapping of `cel::JsonString` to `cel::Json`. -class ABSL_ATTRIBUTE_TRIVIAL_ABI JsonObject final { - private: - using Container = absl::flat_hash_map; - - public: - using key_type = typename Container::key_type; - using mapped_type = typename Container::mapped_type; - using value_type = typename Container::value_type; - using size_type = typename Container::size_type; - using difference_type = typename Container::difference_type; - using reference = typename Container::reference; - using const_reference = typename Container::const_reference; - using pointer = typename Container::pointer; - using const_pointer = typename Container::const_pointer; - using iterator = typename Container::iterator; - using const_iterator = typename Container::const_iterator; - - JsonObject() : impl_(Empty()) {} - - JsonObject(const JsonObject&) = default; - JsonObject(JsonObject&&) = default; - - JsonObject& operator=(const JsonObject&) = default; - JsonObject& operator=(JsonObject&&) = default; - - bool empty() const; - - size_type size() const; - - const_iterator begin() const; - - const_iterator cbegin() const; - - const_iterator end() const; - - const_iterator cend() const; - - template - const_iterator find(const K& key) const; - - template - bool contains(const K& key) const; - - friend bool operator==(const JsonObject& lhs, const JsonObject& rhs); - - friend bool operator!=(const JsonObject& lhs, const JsonObject& rhs); - - template - friend H AbslHashValue(H state, const JsonObject& json_object); - - private: - friend class JsonObjectBuilder; - - static internal::CopyOnWrite Empty(); - - explicit JsonObject(internal::CopyOnWrite impl); - - internal::CopyOnWrite impl_; -}; - -// Json is now fully declared. -template -JsonObjectBuilder::iterator JsonObjectBuilder::find(const K& key) { - return impl_.mutable_get().find(key); -} - -template -bool JsonObjectBuilder::contains(const K& key) { - return impl_.mutable_get().contains(key); -} - -template -std::pair JsonObjectBuilder::insert( - P&& value) { - return impl_.mutable_get().insert(std::forward

(value)); -} - -template -void JsonObjectBuilder::insert(InputIterator first, InputIterator last) { - impl_.mutable_get().insert(std::move(first), std::move(last)); -} - -template -std::pair -JsonObjectBuilder::insert_or_assign(const key_type& k, M&& obj) { - return impl_.mutable_get().insert_or_assign(k, std::forward(obj)); -} - -template -std::pair -JsonObjectBuilder::insert_or_assign(key_type&& k, M&& obj) { - return impl_.mutable_get().insert_or_assign(std::move(k), - std::forward(obj)); -} - -template -std::pair JsonObjectBuilder::try_emplace( - const key_type& key, Args&&... args) { - return impl_.mutable_get().try_emplace(key, std::forward(args)...); -} - -template -std::pair JsonObjectBuilder::try_emplace( - key_type&& key, Args&&... args) { - return impl_.mutable_get().try_emplace(std::move(key), - std::forward(args)...); -} - -template -std::pair JsonObjectBuilder::emplace( - Args&&... args) { - return impl_.mutable_get().emplace(std::forward(args)...); -} - -template -JsonObjectBuilder::size_type JsonObjectBuilder::erase(const K& k) { - return impl_.mutable_get().erase(k); -} - -template -JsonObject::const_iterator JsonObject::find(const K& key) const { - return impl_.get().find(key); -} - -template -bool JsonObject::contains(const K& key) const { - return impl_.get().contains(key); -} - -// `cel::JsonInt` returns `value` as `cel::Json`. If `value` is representable as -// a number, the result with be `cel::JsonNumber`. Otherwise `value` is -// converted to a string and the result will be `cel::JsonString`. -Json JsonInt(int64_t value); - -// `cel::JsonUint` returns `value` as `cel::Json`. If `value` is representable -// as a number, the result with be `cel::JsonNumber`. Otherwise `value` is -// converted to a string and the result will be `cel::JsonString`. -Json JsonUint(uint64_t value); - -// `cel::JsonUint` returns `value` as `cel::Json`. `value` is base64 encoded and -// returned as `cel::JsonString`. -Json JsonBytes(absl::string_view value); -Json JsonBytes(const absl::Cord& value); - -// Serializes `json` as `google.protobuf.Any` with type `google.protobuf.Value`. -absl::StatusOr JsonToAny(const Json& json); -absl::Status JsonToAnyValue(const Json& json, absl::Cord& data); - -// Serializes `json` as `google.protobuf.Any` with type -// `google.protobuf.ListValue`. -absl::StatusOr JsonArrayToAny(const JsonArray& json); -absl::Status JsonArrayToAnyValue(const JsonArray& json, absl::Cord& data); - -// Serializes `json` as `google.protobuf.Any` with type -// `google.protobuf.Struct`. -absl::StatusOr JsonObjectToAny(const JsonObject& json); -absl::Status JsonObjectToAnyValue(const JsonObject& json, absl::Cord& data); - class AnyToJsonConverter { public: virtual ~AnyToJsonConverter() = default; @@ -510,29 +64,6 @@ GetDescriptorPoolAndMessageFactory( return std::pair{descriptor_pool, message_factory}; } -template -JsonArray MakeJsonArray(std::initializer_list il) { - JsonArrayBuilder builder; - builder.reserve(il.size()); - for (const auto& element : il) { - builder.push_back(element); - } - return std::move(builder).Build(); -} - -JsonObject MakeJsonObject( - std::initializer_list> il); - -template -H AbslHashValue(H state, const JsonArray& json_array) { - return H::combine(std::move(state), json_array.impl_.get()); -} - -template -H AbslHashValue(H state, const JsonObject& json_object) { - return H::combine(std::move(state), json_object.impl_.get()); -} - } // namespace cel #endif // THIRD_PARTY_CEL_CPP_COMMON_JSON_H_ diff --git a/common/json_test.cc b/common/json_test.cc deleted file mode 100644 index 36c78a924..000000000 --- a/common/json_test.cc +++ /dev/null @@ -1,160 +0,0 @@ -// 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 "common/json.h" - -#include "absl/hash/hash_testing.h" -#include "absl/strings/escaping.h" -#include "absl/strings/str_cat.h" -#include "absl/strings/string_view.h" -#include "internal/testing.h" - -namespace cel::internal { -namespace { - -using ::testing::ElementsAre; -using ::testing::Eq; -using ::testing::IsFalse; -using ::testing::IsTrue; -using ::testing::UnorderedElementsAre; -using ::testing::VariantWith; - -TEST(Json, DefaultConstructor) { - EXPECT_THAT(Json(), VariantWith(Eq(kJsonNull))); -} - -TEST(Json, NullConstructor) { - EXPECT_THAT(Json(kJsonNull), VariantWith(Eq(kJsonNull))); -} - -TEST(Json, FalseConstructor) { - EXPECT_THAT(Json(false), VariantWith(IsFalse())); -} - -TEST(Json, TrueConstructor) { - EXPECT_THAT(Json(true), VariantWith(IsTrue())); -} - -TEST(Json, NumberConstructor) { - EXPECT_THAT(Json(1.0), VariantWith(1)); -} - -TEST(Json, StringConstructor) { - EXPECT_THAT(Json(JsonString("foo")), VariantWith(Eq("foo"))); -} - -TEST(Json, ArrayConstructor) { - EXPECT_THAT(Json(JsonArray()), VariantWith(Eq(JsonArray()))); -} - -TEST(Json, ObjectConstructor) { - EXPECT_THAT(Json(JsonObject()), VariantWith(Eq(JsonObject()))); -} - -TEST(Json, ImplementsAbslHashCorrectly) { - EXPECT_TRUE(absl::VerifyTypeImplementsAbslHashCorrectly( - {Json(), Json(true), Json(1.0), Json(JsonString("foo")), - Json(JsonArray()), Json(JsonObject())})); -} - -TEST(JsonArrayBuilder, DefaultConstructor) { - JsonArrayBuilder builder; - EXPECT_TRUE(builder.empty()); - EXPECT_EQ(builder.size(), 0); -} - -TEST(JsonArrayBuilder, OneOfEach) { - JsonArrayBuilder builder; - builder.reserve(6); - builder.push_back(kJsonNull); - builder.push_back(true); - builder.push_back(1.0); - builder.push_back(JsonString("foo")); - builder.push_back(JsonArray()); - builder.push_back(JsonObject()); - EXPECT_FALSE(builder.empty()); - EXPECT_EQ(builder.size(), 6); - EXPECT_THAT(builder, ElementsAre(kJsonNull, true, 1.0, JsonString("foo"), - JsonArray(), JsonObject())); - builder.pop_back(); - EXPECT_FALSE(builder.empty()); - EXPECT_EQ(builder.size(), 5); - EXPECT_THAT(builder, ElementsAre(kJsonNull, true, 1.0, JsonString("foo"), - JsonArray())); - builder.clear(); - EXPECT_TRUE(builder.empty()); - EXPECT_EQ(builder.size(), 0); -} - -TEST(JsonObjectBuilder, DefaultConstructor) { - JsonObjectBuilder builder; - EXPECT_TRUE(builder.empty()); - EXPECT_EQ(builder.size(), 0); -} - -TEST(JsonObjectBuilder, OneOfEach) { - JsonObjectBuilder builder; - builder.reserve(6); - builder.insert_or_assign(JsonString("foo"), kJsonNull); - builder.insert_or_assign(JsonString("bar"), true); - builder.insert_or_assign(JsonString("baz"), 1.0); - builder.insert_or_assign(JsonString("qux"), JsonString("foo")); - builder.insert_or_assign(JsonString("quux"), JsonArray()); - builder.insert_or_assign(JsonString("corge"), JsonObject()); - EXPECT_FALSE(builder.empty()); - EXPECT_EQ(builder.size(), 6); - EXPECT_THAT(builder, UnorderedElementsAre( - std::make_pair(JsonString("foo"), kJsonNull), - std::make_pair(JsonString("bar"), true), - std::make_pair(JsonString("baz"), 1.0), - std::make_pair(JsonString("qux"), JsonString("foo")), - std::make_pair(JsonString("quux"), JsonArray()), - std::make_pair(JsonString("corge"), JsonObject()))); - builder.erase(JsonString("corge")); - EXPECT_FALSE(builder.empty()); - EXPECT_EQ(builder.size(), 5); - EXPECT_THAT(builder, UnorderedElementsAre( - std::make_pair(JsonString("foo"), kJsonNull), - std::make_pair(JsonString("bar"), true), - std::make_pair(JsonString("baz"), 1.0), - std::make_pair(JsonString("qux"), JsonString("foo")), - std::make_pair(JsonString("quux"), JsonArray()))); - builder.clear(); - EXPECT_TRUE(builder.empty()); - EXPECT_EQ(builder.size(), 0); -} - -TEST(JsonInt, Basic) { - EXPECT_THAT(JsonInt(1), VariantWith(1.0)); - EXPECT_THAT(JsonInt(std::numeric_limits::max()), - VariantWith( - Eq(absl::StrCat(std::numeric_limits::max())))); -} - -TEST(JsonUint, Basic) { - EXPECT_THAT(JsonUint(1), VariantWith(1.0)); - EXPECT_THAT(JsonUint(std::numeric_limits::max()), - VariantWith( - Eq(absl::StrCat(std::numeric_limits::max())))); -} - -TEST(JsonBytes, Basic) { - EXPECT_THAT(JsonBytes("foo"), - VariantWith(Eq(absl::Base64Escape("foo")))); - EXPECT_THAT(JsonBytes(absl::Cord("foo")), - VariantWith(Eq(absl::Base64Escape("foo")))); -} - -} // namespace -} // namespace cel::internal diff --git a/common/legacy_value.cc b/common/legacy_value.cc index 3e8ba53ef..d6b5130fb 100644 --- a/common/legacy_value.cc +++ b/common/legacy_value.cc @@ -40,7 +40,6 @@ #include "common/allocator.h" #include "common/casting.h" #include "common/internal/arena_string.h" -#include "common/json.h" #include "common/kind.h" #include "common/memory.h" #include "common/type.h" @@ -62,7 +61,6 @@ #include "extensions/protobuf/memory_manager.h" #include "internal/json.h" #include "internal/status_macros.h" -#include "internal/time.h" #include "internal/well_known_types.h" #include "runtime/runtime_options.h" #include "google/protobuf/arena.h" @@ -139,133 +137,6 @@ class CelListIterator final : public ValueIterator { int index_ = 0; }; -absl::StatusOr CelValueToJson(google::protobuf::Arena* arena, CelValue value); - -absl::StatusOr CelValueToJsonString(CelValue value) { - switch (value.type()) { - case CelValue::Type::kString: - return JsonString(value.StringOrDie().value()); - default: - return TypeConversionError(KindToString(value.type()), "string") - .NativeValue(); - } -} - -absl::StatusOr CelListToJsonArray(google::protobuf::Arena* arena, - const CelList* list); - -absl::StatusOr CelMapToJsonObject(google::protobuf::Arena* arena, - const CelMap* map); - -absl::StatusOr MessageWrapperToJsonObject( - google::protobuf::Arena* arena, MessageWrapper message_wrapper); - -absl::StatusOr CelValueToJson(google::protobuf::Arena* arena, CelValue value) { - switch (value.type()) { - case CelValue::Type::kNullType: - return kJsonNull; - case CelValue::Type::kBool: - return value.BoolOrDie(); - case CelValue::Type::kInt64: - return JsonInt(value.Int64OrDie()); - case CelValue::Type::kUint64: - return JsonUint(value.Uint64OrDie()); - case CelValue::Type::kDouble: - return value.DoubleOrDie(); - case CelValue::Type::kString: - return JsonString(value.StringOrDie().value()); - case CelValue::Type::kBytes: - return JsonBytes(value.BytesOrDie().value()); - case CelValue::Type::kMessage: - return MessageWrapperToJsonObject(arena, value.MessageWrapperOrDie()); - case CelValue::Type::kDuration: { - CEL_ASSIGN_OR_RETURN( - auto json, internal::EncodeDurationToJson(value.DurationOrDie())); - return JsonString(std::move(json)); - } - case CelValue::Type::kTimestamp: { - CEL_ASSIGN_OR_RETURN( - auto json, internal::EncodeTimestampToJson(value.TimestampOrDie())); - return JsonString(std::move(json)); - } - case CelValue::Type::kList: - return CelListToJsonArray(arena, value.ListOrDie()); - case CelValue::Type::kMap: - return CelMapToJsonObject(arena, value.MapOrDie()); - case CelValue::Type::kUnknownSet: - ABSL_FALLTHROUGH_INTENDED; - case CelValue::Type::kCelType: - ABSL_FALLTHROUGH_INTENDED; - case CelValue::Type::kError: - ABSL_FALLTHROUGH_INTENDED; - default: - return absl::FailedPreconditionError(absl::StrCat( - CelValue::TypeName(value.type()), " is unserializable to JSON")); - } -} - -absl::StatusOr CelListToJsonArray(google::protobuf::Arena* arena, - const CelList* list) { - JsonArrayBuilder builder; - const auto size = static_cast(list->size()); - builder.reserve(size); - for (size_t index = 0; index < size; ++index) { - CEL_ASSIGN_OR_RETURN( - auto element, - CelValueToJson(arena, list->Get(arena, static_cast(index)))); - builder.push_back(std::move(element)); - } - return std::move(builder).Build(); -} - -absl::StatusOr CelMapToJsonObject(google::protobuf::Arena* arena, - const CelMap* map) { - JsonObjectBuilder builder; - const auto size = static_cast(map->size()); - builder.reserve(size); - CEL_ASSIGN_OR_RETURN(const auto* keys_list, map->ListKeys(arena)); - for (size_t index = 0; index < size; ++index) { - auto key = keys_list->Get(arena, static_cast(index)); - auto value = map->Get(arena, key); - if (!value.has_value()) { - return absl::FailedPreconditionError( - "ListKeys() returned key not present map"); - } - CEL_ASSIGN_OR_RETURN(auto json_key, CelValueToJsonString(key)); - CEL_ASSIGN_OR_RETURN(auto json_value, CelValueToJson(arena, *value)); - if (!builder.insert(std::pair{std::move(json_key), std::move(json_value)}) - .second) { - return absl::FailedPreconditionError( - "duplicate keys encountered serializing map as JSON"); - } - } - return std::move(builder).Build(); -} - -absl::StatusOr MessageWrapperToJsonObject( - google::protobuf::Arena* arena, MessageWrapper message_wrapper) { - JsonObjectBuilder builder; - const auto* type_info = message_wrapper.legacy_type_info(); - const auto* access_apis = type_info->GetAccessApis(message_wrapper); - if (access_apis == nullptr) { - return absl::FailedPreconditionError( - absl::StrCat("LegacyTypeAccessApis missing for type: ", - type_info->GetTypename(message_wrapper))); - } - auto field_names = access_apis->ListFields(message_wrapper); - builder.reserve(field_names.size()); - for (const auto& field_name : field_names) { - CEL_ASSIGN_OR_RETURN( - auto field, - access_apis->GetField(field_name, message_wrapper, - ProtoWrapperTypeOptions::kUnsetNull, - extensions::ProtoMemoryManagerRef(arena))); - CEL_ASSIGN_OR_RETURN(auto json_field, CelValueToJson(arena, field)); - builder.insert_or_assign(JsonString(field_name), std::move(json_field)); - } - return std::move(builder).Build(); -} - std::string cel_common_internal_LegacyListValue_DebugString(uintptr_t impl) { return CelValue::CreateList(AsCelList(impl)).DebugString(); } diff --git a/internal/BUILD b/internal/BUILD index 71bc99bc6..74aba5a40 100644 --- a/internal/BUILD +++ b/internal/BUILD @@ -87,7 +87,6 @@ cc_library( ":proto_wire", ":status_macros", "//common:any", - "//common:json", "@com_google_absl//absl/status:statusor", "@com_google_absl//absl/strings:cord", "@com_google_absl//absl/time", @@ -102,15 +101,12 @@ cc_library( deps = [ ":proto_wire", ":status_macros", - "//common:json", "@com_google_absl//absl/base", - "@com_google_absl//absl/functional:overload", "@com_google_absl//absl/log:absl_check", "@com_google_absl//absl/status", "@com_google_absl//absl/strings:cord", "@com_google_absl//absl/strings:string_view", "@com_google_absl//absl/time", - "@com_google_absl//absl/types:variant", ], ) @@ -718,7 +714,6 @@ cc_library( ":status_macros", ":strings", ":well_known_types", - "//common:json", "//extensions/protobuf/internal:map_reflection", "@com_google_absl//absl/base:core_headers", "@com_google_absl//absl/base:no_destructor", @@ -743,11 +738,9 @@ cc_test( ":json", ":message_type_name", ":parse_text_proto", - ":proto_matchers", ":testing", ":testing_descriptor_pool", ":testing_message_factory", - "//common:json", "@com_google_absl//absl/base:nullability", "@com_google_absl//absl/log:die_if_null", "@com_google_absl//absl/status", diff --git a/internal/deserialize.cc b/internal/deserialize.cc index 15d416834..c37f865f9 100644 --- a/internal/deserialize.cc +++ b/internal/deserialize.cc @@ -23,7 +23,6 @@ #include "absl/strings/cord.h" #include "absl/time/time.h" #include "common/any.h" -#include "common/json.h" #include "internal/proto_wire.h" #include "internal/status_macros.h" @@ -224,111 +223,6 @@ absl::StatusOr DeserializeFloatValueOrDoubleValue( return primitive; } -absl::StatusOr DeserializeValue(const absl::Cord& data) { - Json json = kJsonNull; - ProtoWireDecoder decoder("google.protobuf.Value", data); - while (decoder.HasNext()) { - CEL_ASSIGN_OR_RETURN(auto tag, decoder.ReadTag()); - if (tag == MakeProtoWireTag(1, ProtoWireType::kVarint)) { - CEL_ASSIGN_OR_RETURN(auto unused, decoder.ReadVarint()); - static_cast(unused); - json = kJsonNull; - continue; - } - if (tag == MakeProtoWireTag(2, ProtoWireType::kFixed64)) { - CEL_ASSIGN_OR_RETURN(auto number_value, decoder.ReadFixed64()); - json = number_value; - continue; - } - if (tag == MakeProtoWireTag(3, ProtoWireType::kLengthDelimited)) { - CEL_ASSIGN_OR_RETURN(auto string_value, decoder.ReadLengthDelimited()); - json = std::move(string_value); - continue; - } - if (tag == MakeProtoWireTag(4, ProtoWireType::kVarint)) { - CEL_ASSIGN_OR_RETURN(auto bool_value, decoder.ReadVarint()); - json = bool_value; - continue; - } - if (tag == MakeProtoWireTag(5, ProtoWireType::kLengthDelimited)) { - CEL_ASSIGN_OR_RETURN(auto struct_value, decoder.ReadLengthDelimited()); - CEL_ASSIGN_OR_RETURN(auto json_object, DeserializeStruct(struct_value)); - json = std::move(json_object); - continue; - } - if (tag == MakeProtoWireTag(6, ProtoWireType::kLengthDelimited)) { - CEL_ASSIGN_OR_RETURN(auto list_value, decoder.ReadLengthDelimited()); - CEL_ASSIGN_OR_RETURN(auto json_array, DeserializeListValue(list_value)); - json = std::move(json_array); - continue; - } - CEL_RETURN_IF_ERROR(decoder.SkipLengthValue()); - } - decoder.EnsureFullyDecoded(); - return json; -} - -absl::StatusOr DeserializeListValue(const absl::Cord& data) { - JsonArrayBuilder array_builder; - ProtoWireDecoder decoder("google.protobuf.ListValue", data); - while (decoder.HasNext()) { - CEL_ASSIGN_OR_RETURN(auto tag, decoder.ReadTag()); - if (tag == MakeProtoWireTag(1, ProtoWireType::kLengthDelimited)) { - // values - CEL_ASSIGN_OR_RETURN(auto element_value, decoder.ReadLengthDelimited()); - CEL_ASSIGN_OR_RETURN(auto element, DeserializeValue(element_value)); - array_builder.push_back(std::move(element)); - continue; - } - CEL_RETURN_IF_ERROR(decoder.SkipLengthValue()); - } - decoder.EnsureFullyDecoded(); - return std::move(array_builder).Build(); -} - -absl::StatusOr DeserializeStruct(const absl::Cord& data) { - JsonObjectBuilder object_builder; - ProtoWireDecoder decoder("google.protobuf.Struct", data); - while (decoder.HasNext()) { - CEL_ASSIGN_OR_RETURN(auto tag, decoder.ReadTag()); - if (tag == MakeProtoWireTag(1, ProtoWireType::kLengthDelimited)) { - // fields - CEL_ASSIGN_OR_RETURN(auto fields_value, decoder.ReadLengthDelimited()); - absl::Cord field_name; - Json field_value = kJsonNull; - ProtoWireDecoder fields_decoder("google.protobuf.Struct.FieldsEntry", - fields_value); - while (fields_decoder.HasNext()) { - CEL_ASSIGN_OR_RETURN(auto fields_tag, fields_decoder.ReadTag()); - if (fields_tag == - MakeProtoWireTag(1, ProtoWireType::kLengthDelimited)) { - // key - CEL_ASSIGN_OR_RETURN(field_name, - fields_decoder.ReadLengthDelimited()); - continue; - } - if (fields_tag == - MakeProtoWireTag(2, ProtoWireType::kLengthDelimited)) { - // value - CEL_ASSIGN_OR_RETURN(auto field_value_value, - fields_decoder.ReadLengthDelimited()); - CEL_ASSIGN_OR_RETURN(field_value, - DeserializeValue(field_value_value)); - continue; - } - CEL_RETURN_IF_ERROR(fields_decoder.SkipLengthValue()); - } - fields_decoder.EnsureFullyDecoded(); - object_builder.insert_or_assign(std::move(field_name), - std::move(field_value)); - continue; - } - CEL_RETURN_IF_ERROR(decoder.SkipLengthValue()); - } - decoder.EnsureFullyDecoded(); - return std::move(object_builder).Build(); -} - absl::StatusOr DeserializeAny(const absl::Cord& data) { absl::Cord type_url; absl::Cord value; diff --git a/internal/deserialize.h b/internal/deserialize.h index 719c972db..b932c67c8 100644 --- a/internal/deserialize.h +++ b/internal/deserialize.h @@ -21,7 +21,6 @@ #include "absl/status/statusor.h" #include "absl/strings/cord.h" #include "absl/time/time.h" -#include "common/json.h" namespace cel::internal { @@ -50,12 +49,6 @@ absl::StatusOr DeserializeDoubleValue(const absl::Cord& data); absl::StatusOr DeserializeFloatValueOrDoubleValue( const absl::Cord& data); -absl::StatusOr DeserializeValue(const absl::Cord& data); - -absl::StatusOr DeserializeListValue(const absl::Cord& data); - -absl::StatusOr DeserializeStruct(const absl::Cord& data); - absl::StatusOr DeserializeAny(const absl::Cord& data); } // namespace cel::internal diff --git a/internal/json.cc b/internal/json.cc index d1bf16ade..bd261ac09 100644 --- a/internal/json.cc +++ b/internal/json.cc @@ -15,7 +15,6 @@ #include "internal/json.h" #include -#include #include #include #include @@ -42,7 +41,6 @@ #include "absl/strings/str_join.h" #include "absl/strings/string_view.h" #include "absl/types/variant.h" -#include "common/json.h" #include "extensions/protobuf/internal/map_reflection.h" #include "internal/status_macros.h" #include "internal/strings.h" @@ -2043,449 +2041,4 @@ bool JsonMapEquals(const google::protobuf::MessageLite& lhs, google::protobuf::DownCastMessage(rhs)); } -namespace { - -struct DynamicProtoJsonToNativeJsonState { - ValueReflection value_reflection; - ListValueReflection list_value_reflection; - StructReflection struct_reflection; - std::string scratch; - - absl::Status Initialize(const google::protobuf::Message& proto) { - CEL_RETURN_IF_ERROR(value_reflection.Initialize(proto.GetDescriptor())); - CEL_RETURN_IF_ERROR(list_value_reflection.Initialize( - value_reflection.GetListValueDescriptor())); - CEL_RETURN_IF_ERROR( - struct_reflection.Initialize(value_reflection.GetStructDescriptor())); - return absl::OkStatus(); - } - - absl::Status InitializeListValue(const google::protobuf::Message& proto) { - CEL_RETURN_IF_ERROR( - list_value_reflection.Initialize(proto.GetDescriptor())); - CEL_RETURN_IF_ERROR(value_reflection.Initialize( - list_value_reflection.GetValueDescriptor())); - CEL_RETURN_IF_ERROR( - struct_reflection.Initialize(value_reflection.GetStructDescriptor())); - return absl::OkStatus(); - } - - absl::Status InitializeStruct(const google::protobuf::Message& proto) { - CEL_RETURN_IF_ERROR(struct_reflection.Initialize(proto.GetDescriptor())); - CEL_RETURN_IF_ERROR( - value_reflection.Initialize(struct_reflection.GetValueDescriptor())); - CEL_RETURN_IF_ERROR(list_value_reflection.Initialize( - value_reflection.GetListValueDescriptor())); - return absl::OkStatus(); - } - - absl::StatusOr ToNativeJson(const google::protobuf::Message& proto) { - const auto kind_case = value_reflection.GetKindCase(proto); - switch (kind_case) { - case google::protobuf::Value::KIND_NOT_SET: - ABSL_FALLTHROUGH_INTENDED; - case google::protobuf::Value::kNullValue: - return kJsonNull; - case google::protobuf::Value::kBoolValue: - return JsonBool(value_reflection.GetBoolValue(proto)); - case google::protobuf::Value::kNumberValue: - return JsonNumber(value_reflection.GetNumberValue(proto)); - case google::protobuf::Value::kStringValue: - return absl::visit( - absl::Overload( - [](absl::string_view string) -> JsonString { - return JsonString(string); - }, - [](absl::Cord&& cord) -> JsonString { return cord; }), - AsVariant(value_reflection.GetStringValue(proto, scratch))); - case google::protobuf::Value::kListValue: - return ToNativeJsonList(value_reflection.GetListValue(proto)); - case google::protobuf::Value::kStructValue: - return ToNativeJsonMap(value_reflection.GetStructValue(proto)); - default: - return absl::InvalidArgumentError( - absl::StrCat("unexpected value kind case: ", kind_case)); - } - } - - absl::StatusOr ToNativeJsonList(const google::protobuf::Message& proto) { - const int proto_size = list_value_reflection.ValuesSize(proto); - JsonArrayBuilder builder; - builder.reserve(static_cast(proto_size)); - for (int i = 0; i < proto_size; ++i) { - CEL_ASSIGN_OR_RETURN( - auto value, ToNativeJson(list_value_reflection.Values(proto, i))); - builder.push_back(std::move(value)); - } - return std::move(builder).Build(); - } - - absl::StatusOr ToNativeJsonMap(const google::protobuf::Message& proto) { - const int proto_size = struct_reflection.FieldsSize(proto); - JsonObjectBuilder builder; - builder.reserve(static_cast(proto_size)); - auto struct_proto_begin = struct_reflection.BeginFields(proto); - auto struct_proto_end = struct_reflection.EndFields(proto); - for (; struct_proto_begin != struct_proto_end; ++struct_proto_begin) { - CEL_ASSIGN_OR_RETURN( - auto value, - ToNativeJson(struct_proto_begin.GetValueRef().GetMessageValue())); - builder.insert_or_assign( - JsonString(struct_proto_begin.GetKey().GetStringValue()), - std::move(value)); - } - return std::move(builder).Build(); - } -}; - -} // namespace - -absl::StatusOr ProtoJsonToNativeJson(const google::protobuf::Message& proto) { - DynamicProtoJsonToNativeJsonState state; - CEL_RETURN_IF_ERROR(state.Initialize(proto)); - return state.ToNativeJson(proto); -} - -absl::StatusOr ProtoJsonToNativeJson( - const google::protobuf::Value& proto) { - const auto kind_case = ValueReflection::GetKindCase(proto); - switch (kind_case) { - case google::protobuf::Value::KIND_NOT_SET: - ABSL_FALLTHROUGH_INTENDED; - case google::protobuf::Value::kNullValue: - return kJsonNull; - case google::protobuf::Value::kBoolValue: - return JsonBool(ValueReflection::GetBoolValue(proto)); - case google::protobuf::Value::kNumberValue: - return JsonNumber(ValueReflection::GetNumberValue(proto)); - case google::protobuf::Value::kStringValue: - return JsonString(ValueReflection::GetStringValue(proto)); - case google::protobuf::Value::kListValue: - return ProtoJsonListToNativeJsonList( - ValueReflection::GetListValue(proto)); - case google::protobuf::Value::kStructValue: - return ProtoJsonMapToNativeJsonMap( - ValueReflection::GetStructValue(proto)); - default: - return absl::InvalidArgumentError( - absl::StrCat("unexpected value kind case: ", kind_case)); - } -} -absl::StatusOr ProtoJsonListToNativeJsonList( - const google::protobuf::Message& proto) { - DynamicProtoJsonToNativeJsonState state; - CEL_RETURN_IF_ERROR(state.InitializeListValue(proto)); - return state.ToNativeJsonList(proto); -} - -absl::StatusOr ProtoJsonListToNativeJsonList( - const google::protobuf::ListValue& proto) { - const int proto_size = ListValueReflection::ValuesSize(proto); - JsonArrayBuilder builder; - builder.reserve(static_cast(proto_size)); - for (int i = 0; i < proto_size; ++i) { - CEL_ASSIGN_OR_RETURN( - auto value, - ProtoJsonToNativeJson(ListValueReflection::Values(proto, i))); - builder.push_back(std::move(value)); - } - return std::move(builder).Build(); -} - -absl::StatusOr ProtoJsonMapToNativeJsonMap( - const google::protobuf::Message& proto) { - DynamicProtoJsonToNativeJsonState state; - CEL_RETURN_IF_ERROR(state.InitializeStruct(proto)); - return state.ToNativeJsonMap(proto); -} - -absl::StatusOr ProtoJsonMapToNativeJsonMap( - const google::protobuf::Struct& proto) { - const int proto_size = StructReflection::FieldsSize(proto); - JsonObjectBuilder builder; - builder.reserve(static_cast(proto_size)); - auto struct_proto_begin = StructReflection::BeginFields(proto); - auto struct_proto_end = StructReflection::EndFields(proto); - for (; struct_proto_begin != struct_proto_end; ++struct_proto_begin) { - CEL_ASSIGN_OR_RETURN(auto value, - ProtoJsonToNativeJson(struct_proto_begin->second)); - builder.insert_or_assign(JsonString(struct_proto_begin->first), - std::move(value)); - } - return std::move(builder).Build(); -} - -namespace { - -class JsonMutator { - public: - virtual ~JsonMutator() = default; - - virtual void SetNullValue( - absl::Nonnull message) const = 0; - - virtual void SetBoolValue(absl::Nonnull message, - bool value) const = 0; - - virtual void SetNumberValue(absl::Nonnull message, - double value) const = 0; - - virtual void SetStringValue(absl::Nonnull message, - const absl::Cord& value) const = 0; - - virtual absl::Nonnull MutableListValue( - absl::Nonnull message) const = 0; - - virtual absl::Nonnull AddValues( - absl::Nonnull message) const = 0; - - virtual absl::Nonnull MutableStructValue( - absl::Nonnull message) const = 0; - - virtual absl::Nonnull InsertField( - absl::Nonnull message, - absl::string_view name) const = 0; -}; - -class GeneratedJsonMutator final : public JsonMutator { - public: - static absl::Nonnull Singleton() { - static const absl::NoDestructor instance; - return &*instance; - } - - void SetNullValue( - absl::Nonnull message) const override { - ValueReflection::SetNullValue( - google::protobuf::DownCastMessage(message)); - } - - void SetBoolValue(absl::Nonnull message, - bool value) const override { - ValueReflection::SetBoolValue( - google::protobuf::DownCastMessage(message), value); - } - - void SetNumberValue(absl::Nonnull message, - double value) const override { - ValueReflection::SetNumberValue( - google::protobuf::DownCastMessage(message), value); - } - - void SetStringValue(absl::Nonnull message, - const absl::Cord& value) const override { - ValueReflection::SetStringValue( - google::protobuf::DownCastMessage(message), value); - } - - absl::Nonnull MutableListValue( - absl::Nonnull message) const override { - return ValueReflection::MutableListValue( - google::protobuf::DownCastMessage(message)); - } - - absl::Nonnull AddValues( - absl::Nonnull message) const override { - return ListValueReflection::AddValues( - google::protobuf::DownCastMessage(message)); - } - - absl::Nonnull MutableStructValue( - absl::Nonnull message) const override { - return ValueReflection::MutableStructValue( - google::protobuf::DownCastMessage(message)); - } - - absl::Nonnull InsertField( - absl::Nonnull message, - absl::string_view name) const override { - return StructReflection::InsertField( - google::protobuf::DownCastMessage(message), name); - } -}; - -class DynamicJsonMutator final : public JsonMutator { - public: - absl::Status InitializeValue( - absl::Nonnull descriptor) { - CEL_RETURN_IF_ERROR(value_reflection_.Initialize(descriptor)); - CEL_RETURN_IF_ERROR(list_value_reflection_.Initialize( - value_reflection_.GetListValueDescriptor())); - CEL_RETURN_IF_ERROR( - struct_reflection_.Initialize(value_reflection_.GetStructDescriptor())); - return absl::OkStatus(); - } - - absl::Status InitializeListValue( - absl::Nonnull descriptor) { - CEL_RETURN_IF_ERROR(list_value_reflection_.Initialize(descriptor)); - CEL_RETURN_IF_ERROR(value_reflection_.Initialize( - list_value_reflection_.GetValueDescriptor())); - CEL_RETURN_IF_ERROR( - struct_reflection_.Initialize(value_reflection_.GetStructDescriptor())); - return absl::OkStatus(); - } - - absl::Status InitializeStruct( - absl::Nonnull descriptor) { - CEL_RETURN_IF_ERROR(struct_reflection_.Initialize(descriptor)); - CEL_RETURN_IF_ERROR( - value_reflection_.Initialize(struct_reflection_.GetValueDescriptor())); - CEL_RETURN_IF_ERROR(list_value_reflection_.Initialize( - value_reflection_.GetListValueDescriptor())); - return absl::OkStatus(); - } - - void SetNullValue( - absl::Nonnull message) const override { - value_reflection_.SetNullValue( - google::protobuf::DownCastMessage(message)); - } - - void SetBoolValue(absl::Nonnull message, - bool value) const override { - value_reflection_.SetBoolValue( - google::protobuf::DownCastMessage(message), value); - } - - void SetNumberValue(absl::Nonnull message, - double value) const override { - value_reflection_.SetNumberValue( - google::protobuf::DownCastMessage(message), value); - } - - void SetStringValue(absl::Nonnull message, - const absl::Cord& value) const override { - value_reflection_.SetStringValue( - google::protobuf::DownCastMessage(message), value); - } - - absl::Nonnull MutableListValue( - absl::Nonnull message) const override { - return value_reflection_.MutableListValue( - google::protobuf::DownCastMessage(message)); - } - - absl::Nonnull AddValues( - absl::Nonnull message) const override { - return list_value_reflection_.AddValues( - google::protobuf::DownCastMessage(message)); - } - - absl::Nonnull MutableStructValue( - absl::Nonnull message) const override { - return value_reflection_.MutableStructValue( - google::protobuf::DownCastMessage(message)); - } - - absl::Nonnull InsertField( - absl::Nonnull message, - absl::string_view name) const override { - return struct_reflection_.InsertField( - google::protobuf::DownCastMessage(message), name); - } - - private: - ValueReflection value_reflection_; - ListValueReflection list_value_reflection_; - StructReflection struct_reflection_; -}; - -class NativeJsonToProtoJsonState { - public: - explicit NativeJsonToProtoJsonState(absl::Nonnull mutator) - : mutator_(mutator) {} - - absl::Status ToProtoJson(const Json& json, - absl::Nonnull proto) { - return absl::visit( - absl::Overload( - [&](JsonNull) -> absl::Status { - mutator_->SetNullValue(proto); - return absl::OkStatus(); - }, - [&](JsonBool value) -> absl::Status { - mutator_->SetBoolValue(proto, value); - return absl::OkStatus(); - }, - [&](JsonNumber value) -> absl::Status { - mutator_->SetNumberValue(proto, value); - return absl::OkStatus(); - }, - [&](const JsonString& value) -> absl::Status { - mutator_->SetStringValue(proto, value); - return absl::OkStatus(); - }, - [&](const JsonArray& value) -> absl::Status { - return ToProtoJsonList(value, mutator_->MutableListValue(proto)); - }, - [&](const JsonObject& value) -> absl::Status { - return ToProtoJsonMap(value, mutator_->MutableStructValue(proto)); - }), - json); - } - - absl::Status ToProtoJsonList(const JsonArray& json, - absl::Nonnull proto) { - for (const auto& element : json) { - CEL_RETURN_IF_ERROR(ToProtoJson(element, mutator_->AddValues(proto))); - } - return absl::OkStatus(); - } - - absl::Status ToProtoJsonMap(const JsonObject& json, - absl::Nonnull proto) { - for (const auto& entry : json) { - CEL_RETURN_IF_ERROR(ToProtoJson( - entry.second, - mutator_->InsertField(proto, static_cast(entry.first)))); - } - return absl::OkStatus(); - } - - private: - absl::Nonnull const mutator_; -}; - -} // namespace - -absl::Status NativeJsonToProtoJson(const Json& json, - absl::Nonnull proto) { - DynamicJsonMutator mutator; - CEL_RETURN_IF_ERROR(mutator.InitializeValue(proto->GetDescriptor())); - return NativeJsonToProtoJsonState(&mutator).ToProtoJson(json, proto); -} - -absl::Status NativeJsonToProtoJson( - const Json& json, absl::Nonnull proto) { - return NativeJsonToProtoJsonState(GeneratedJsonMutator::Singleton()) - .ToProtoJson(json, proto); -} - -absl::Status NativeJsonListToProtoJsonList( - const JsonArray& json, absl::Nonnull proto) { - DynamicJsonMutator mutator; - CEL_RETURN_IF_ERROR(mutator.InitializeListValue(proto->GetDescriptor())); - return NativeJsonToProtoJsonState(&mutator).ToProtoJsonList(json, proto); -} - -absl::Status NativeJsonListToProtoJsonList( - const JsonArray& json, absl::Nonnull proto) { - return NativeJsonToProtoJsonState(GeneratedJsonMutator::Singleton()) - .ToProtoJsonList(json, proto); -} - -absl::Status NativeJsonMapToProtoJsonMap( - const JsonObject& json, absl::Nonnull proto) { - DynamicJsonMutator mutator; - CEL_RETURN_IF_ERROR(mutator.InitializeStruct(proto->GetDescriptor())); - return NativeJsonToProtoJsonState(&mutator).ToProtoJsonMap(json, proto); -} - -absl::Status NativeJsonMapToProtoJsonMap( - const JsonObject& json, absl::Nonnull proto) { - return NativeJsonToProtoJsonState(GeneratedJsonMutator::Singleton()) - .ToProtoJsonMap(json, proto); -} - } // namespace cel::internal diff --git a/internal/json.h b/internal/json.h index a4f953918..a2ef30845 100644 --- a/internal/json.h +++ b/internal/json.h @@ -20,8 +20,6 @@ #include "google/protobuf/struct.pb.h" #include "absl/base/nullability.h" #include "absl/status/status.h" -#include "absl/status/statusor.h" -#include "common/json.h" #include "google/protobuf/descriptor.h" #include "google/protobuf/message.h" @@ -138,52 +136,6 @@ bool JsonMapEquals(const google::protobuf::Message& lhs, const google::protobuf: bool JsonMapEquals(const google::protobuf::MessageLite& lhs, const google::protobuf::MessageLite& rhs); -// Temporary function which converts from `google.protobuf.Value` to -// `cel::Json`. In future `cel::Json` will be killed in favor of pure proto. -absl::StatusOr ProtoJsonToNativeJson(const google::protobuf::Message& proto); -absl::StatusOr ProtoJsonToNativeJson( - const google::protobuf::Value& proto); - -// Temporary function which converts from `google.protobuf.ListValue` to -// `cel::JsonArray`. In future `cel::Json` will be killed in favor of pure -// proto. -absl::StatusOr ProtoJsonListToNativeJsonList( - const google::protobuf::Message& proto); -absl::StatusOr ProtoJsonListToNativeJsonList( - const google::protobuf::ListValue& proto); - -// Temporary function which converts from `google.protobuf.Struct` to -// `cel::JsonObject`. In future `cel::Json` will be killed in favor of pure -// proto. -absl::StatusOr ProtoJsonMapToNativeJsonMap( - const google::protobuf::Message& proto); -absl::StatusOr ProtoJsonMapToNativeJsonMap( - const google::protobuf::Struct& proto); - -// Temporary function which converts from `cel::Json` to -// `google.protobuf.Value`. In future `cel::Json` will be killed in favor of -// pure proto. -absl::Status NativeJsonToProtoJson(const Json& json, - absl::Nonnull proto); -absl::Status NativeJsonToProtoJson( - const Json& json, absl::Nonnull proto); - -// Temporary function which converts from `cel::JsonArray` to -// `google.protobuf.ListValue`. In future `cel::JsonArray` will be killed in -// favor of pure proto. -absl::Status NativeJsonListToProtoJsonList( - const JsonArray& json, absl::Nonnull proto); -absl::Status NativeJsonListToProtoJsonList( - const JsonArray& json, absl::Nonnull proto); - -// Temporary function which converts from `cel::JsonObject` to -// `google.protobuf.Struct`. In future `cel::JsonObject` will be killed in -// favor of pure proto. -absl::Status NativeJsonMapToProtoJsonMap(const JsonObject& json, - absl::Nonnull proto); -absl::Status NativeJsonMapToProtoJsonMap( - const JsonObject& json, absl::Nonnull proto); - } // namespace cel::internal #endif // THIRD_PARTY_CEL_CPP_INTERNAL_JSON_H_ diff --git a/internal/json_test.cc b/internal/json_test.cc index 262d31fa3..02ff4f452 100644 --- a/internal/json_test.cc +++ b/internal/json_test.cc @@ -25,11 +25,9 @@ #include "absl/status/status.h" #include "absl/status/status_matchers.h" #include "absl/strings/string_view.h" -#include "common/json.h" #include "internal/equals_text_proto.h" #include "internal/message_type_name.h" #include "internal/parse_text_proto.h" -#include "internal/proto_matchers.h" #include "internal/testing.h" #include "internal/testing_descriptor_pool.h" #include "internal/testing_message_factory.h" @@ -42,13 +40,10 @@ namespace cel::internal { namespace { using ::absl_testing::IsOk; -using ::absl_testing::IsOkAndHolds; using ::absl_testing::StatusIs; -using ::cel::internal::test::EqualsProto; using ::testing::AnyOf; using ::testing::HasSubstr; using ::testing::Test; -using ::testing::VariantWith; using TestAllTypesProto3 = ::cel::expr::conformance::proto3::TestAllTypes; @@ -2991,171 +2986,5 @@ TEST_F(JsonEqualsTest, Map_Map_Dynamic_Dynamic) { )pb")))); } -class ProtoJsonNativeJsonTest : public Test { - public: - absl::Nonnull arena() { return &arena_; } - - absl::Nonnull descriptor_pool() { - return GetTestingDescriptorPool(); - } - - absl::Nonnull message_factory() { - return GetTestingMessageFactory(); - } - - template - auto GeneratedParseTextProto(absl::string_view text) { - return ::cel::internal::GeneratedParseTextProto( - arena(), text, descriptor_pool(), message_factory()); - } - - template - auto DynamicParseTextProto(absl::string_view text) { - return ::cel::internal::DynamicParseTextProto( - arena(), text, descriptor_pool(), message_factory()); - } - - private: - google::protobuf::Arena arena_; -}; - -TEST_F(ProtoJsonNativeJsonTest, Null_Generated) { - auto message = GeneratedParseTextProto( - R"pb(null_value: NULL_VALUE)pb"); - EXPECT_THAT(ProtoJsonToNativeJson(*message), - IsOkAndHolds(VariantWith(kJsonNull))); - auto* other_message = message->New(arena()); - EXPECT_THAT(NativeJsonToProtoJson(kJsonNull, other_message), IsOk()); - EXPECT_THAT(*other_message, EqualsProto(*message)); -} - -TEST_F(ProtoJsonNativeJsonTest, Null_Dynamic) { - auto message = DynamicParseTextProto( - R"pb(null_value: NULL_VALUE)pb"); - EXPECT_THAT(ProtoJsonToNativeJson(*message), - IsOkAndHolds(VariantWith(kJsonNull))); - auto* other_message = message->New(arena()); - EXPECT_THAT(NativeJsonToProtoJson(kJsonNull, other_message), IsOk()); - EXPECT_THAT(*other_message, EqualsProto(*message)); -} - -TEST_F(ProtoJsonNativeJsonTest, Bool_Generated) { - auto message = GeneratedParseTextProto( - R"pb(bool_value: true)pb"); - EXPECT_THAT(ProtoJsonToNativeJson(*message), - IsOkAndHolds(VariantWith(true))); - auto* other_message = message->New(arena()); - EXPECT_THAT(NativeJsonToProtoJson(true, other_message), IsOk()); - EXPECT_THAT(*other_message, EqualsProto(*message)); -} - -TEST_F(ProtoJsonNativeJsonTest, Bool_Dynamic) { - auto message = - DynamicParseTextProto(R"pb(bool_value: true)pb"); - EXPECT_THAT(ProtoJsonToNativeJson(*message), - IsOkAndHolds(VariantWith(true))); - auto* other_message = message->New(arena()); - EXPECT_THAT(NativeJsonToProtoJson(true, other_message), IsOk()); - EXPECT_THAT(*other_message, EqualsProto(*message)); -} - -TEST_F(ProtoJsonNativeJsonTest, Number_Generated) { - auto message = GeneratedParseTextProto( - R"pb(number_value: 1.0)pb"); - EXPECT_THAT(ProtoJsonToNativeJson(*message), - IsOkAndHolds(VariantWith(1.0))); - auto* other_message = message->New(arena()); - EXPECT_THAT(NativeJsonToProtoJson(1.0, other_message), IsOk()); - EXPECT_THAT(*other_message, EqualsProto(*message)); -} - -TEST_F(ProtoJsonNativeJsonTest, Number_Dynamic) { - auto message = DynamicParseTextProto( - R"pb(number_value: 1.0)pb"); - EXPECT_THAT(ProtoJsonToNativeJson(*message), - IsOkAndHolds(VariantWith(1.0))); - auto* other_message = message->New(arena()); - EXPECT_THAT(NativeJsonToProtoJson(1.0, other_message), IsOk()); - EXPECT_THAT(*other_message, EqualsProto(*message)); -} - -TEST_F(ProtoJsonNativeJsonTest, String_Generated) { - auto message = GeneratedParseTextProto( - R"pb(string_value: "foo")pb"); - EXPECT_THAT(ProtoJsonToNativeJson(*message), - IsOkAndHolds(VariantWith(JsonString("foo")))); - auto* other_message = message->New(arena()); - EXPECT_THAT(NativeJsonToProtoJson(JsonString("foo"), other_message), IsOk()); - EXPECT_THAT(*other_message, EqualsProto(*message)); -} - -TEST_F(ProtoJsonNativeJsonTest, String_Dynamic) { - auto message = DynamicParseTextProto( - R"pb(string_value: "foo")pb"); - EXPECT_THAT(ProtoJsonToNativeJson(*message), - IsOkAndHolds(VariantWith(JsonString("foo")))); - auto* other_message = message->New(arena()); - EXPECT_THAT(NativeJsonToProtoJson(JsonString("foo"), other_message), IsOk()); - EXPECT_THAT(*other_message, EqualsProto(*message)); -} - -TEST_F(ProtoJsonNativeJsonTest, List_Generated) { - auto message = GeneratedParseTextProto( - R"pb(list_value: { values { bool_value: true } })pb"); - EXPECT_THAT(ProtoJsonToNativeJson(*message), - IsOkAndHolds(VariantWith(MakeJsonArray({true})))); - auto* other_message = message->New(arena()); - EXPECT_THAT(NativeJsonToProtoJson(MakeJsonArray({true}), other_message), - IsOk()); - EXPECT_THAT(*other_message, EqualsProto(*message)); -} - -TEST_F(ProtoJsonNativeJsonTest, List_Dynamic) { - auto message = DynamicParseTextProto( - R"pb(list_value: { values { bool_value: true } })pb"); - EXPECT_THAT(ProtoJsonToNativeJson(*message), - IsOkAndHolds(VariantWith(MakeJsonArray({true})))); - auto* other_message = message->New(arena()); - EXPECT_THAT(NativeJsonToProtoJson(MakeJsonArray({true}), other_message), - IsOk()); - EXPECT_THAT(*other_message, EqualsProto(*message)); -} - -TEST_F(ProtoJsonNativeJsonTest, Struct_Generated) { - auto message = GeneratedParseTextProto( - R"pb(struct_value: { - fields { - key: "foo" - value: { bool_value: true } - } - })pb"); - EXPECT_THAT(ProtoJsonToNativeJson(*message), - IsOkAndHolds(VariantWith( - MakeJsonObject({{JsonString("foo"), true}})))); - auto* other_message = message->New(arena()); - EXPECT_THAT(NativeJsonToProtoJson(MakeJsonObject({{JsonString("foo"), true}}), - other_message), - IsOk()); - EXPECT_THAT(*other_message, EqualsProto(*message)); -} - -TEST_F(ProtoJsonNativeJsonTest, Struct_Dynamic) { - auto message = DynamicParseTextProto( - R"pb(struct_value: { - fields { - key: "foo" - value: { bool_value: true } - } - })pb"); - EXPECT_THAT(ProtoJsonToNativeJson(*message), - IsOkAndHolds(VariantWith( - MakeJsonObject({{JsonString("foo"), true}})))); - auto* other_message = message->New(arena()); - EXPECT_THAT(NativeJsonToProtoJson(MakeJsonObject({{JsonString("foo"), true}}), - other_message), - IsOk()); - EXPECT_THAT(*other_message, EqualsProto(*message)); -} - } // namespace } // namespace cel::internal diff --git a/internal/serialize.cc b/internal/serialize.cc index 847f49ae9..490eac471 100644 --- a/internal/serialize.cc +++ b/internal/serialize.cc @@ -18,14 +18,11 @@ #include #include "absl/base/casts.h" -#include "absl/functional/overload.h" #include "absl/log/absl_check.h" #include "absl/status/status.h" #include "absl/strings/cord.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" -#include "absl/types/variant.h" -#include "common/json.h" #include "internal/proto_wire.h" #include "internal/status_macros.h" @@ -134,81 +131,6 @@ size_t SerializedDoubleValueSize(double value) { : 0; } -size_t SerializedValueSize(const Json& value) { - return absl::visit( - absl::Overload( - [](JsonNull) -> size_t { - return VarintSize(MakeProtoWireTag(1, ProtoWireType::kVarint)) + - VarintSize(0); - }, - [](JsonBool value) -> size_t { - return VarintSize(MakeProtoWireTag(4, ProtoWireType::kVarint)) + - VarintSize(value); - }, - [](JsonNumber value) -> size_t { - return VarintSize(MakeProtoWireTag(2, ProtoWireType::kFixed64)) + 8; - }, - [](const JsonString& value) -> size_t { - return VarintSize( - MakeProtoWireTag(3, ProtoWireType::kLengthDelimited)) + - VarintSize(value.size()) + value.size(); - }, - [](const JsonArray& value) -> size_t { - size_t value_size = SerializedListValueSize(value); - return VarintSize( - MakeProtoWireTag(6, ProtoWireType::kLengthDelimited)) + - VarintSize(value_size) + value_size; - }, - [](const JsonObject& value) -> size_t { - size_t value_size = SerializedStructSize(value); - return VarintSize( - MakeProtoWireTag(5, ProtoWireType::kLengthDelimited)) + - VarintSize(value_size) + value_size; - }), - value); -} - -size_t SerializedListValueSize(const JsonArray& value) { - size_t serialized_size = 0; - if (!value.empty()) { - size_t tag_size = - VarintSize(MakeProtoWireTag(1, ProtoWireType::kLengthDelimited)); - for (const auto& element : value) { - size_t value_size = SerializedValueSize(element); - serialized_size += tag_size + VarintSize(value_size) + value_size; - } - } - return serialized_size; -} - -namespace { - -size_t SerializedStructFieldSize(const JsonString& name, const Json& value) { - size_t name_size = - VarintSize(MakeProtoWireTag(1, ProtoWireType::kLengthDelimited)) + - VarintSize(name.size()) + name.size(); - size_t value_size = SerializedValueSize(value); - value_size = - VarintSize(MakeProtoWireTag(2, ProtoWireType::kLengthDelimited)) + - VarintSize(value_size) + value_size; - return name_size + value_size; -} - -} // namespace - -size_t SerializedStructSize(const JsonObject& value) { - size_t serialized_size = 0; - if (!value.empty()) { - size_t tag_size = - VarintSize(MakeProtoWireTag(1, ProtoWireType::kLengthDelimited)); - for (const auto& entry : value) { - size_t value_size = SerializedStructFieldSize(entry.first, entry.second); - serialized_size += tag_size + VarintSize(value_size) + value_size; - } - } - return serialized_size; -} - // NOTE: We use ABSL_DCHECK below to assert that the resulting size of // serializing is the same as the preflighting size calculation functions. They // must be the same, and ABSL_DCHECK is the cheapest way of ensuring this @@ -370,30 +292,4 @@ absl::Status SerializeDoubleValue(double value, absl::Cord& serialized_value) { return absl::OkStatus(); } -absl::Status SerializeValue(const Json& value, absl::Cord& serialized_value) { - size_t original_size = serialized_value.size(); - CEL_RETURN_IF_ERROR(JsonToAnyValue(value, serialized_value)); - ABSL_DCHECK_EQ(serialized_value.size() - original_size, - SerializedValueSize(value)); - return absl::OkStatus(); -} - -absl::Status SerializeListValue(const JsonArray& value, - absl::Cord& serialized_value) { - size_t original_size = serialized_value.size(); - CEL_RETURN_IF_ERROR(JsonArrayToAnyValue(value, serialized_value)); - ABSL_DCHECK_EQ(serialized_value.size() - original_size, - SerializedListValueSize(value)); - return absl::OkStatus(); -} - -absl::Status SerializeStruct(const JsonObject& value, - absl::Cord& serialized_value) { - size_t original_size = serialized_value.size(); - CEL_RETURN_IF_ERROR(JsonObjectToAnyValue(value, serialized_value)); - ABSL_DCHECK_EQ(serialized_value.size() - original_size, - SerializedStructSize(value)); - return absl::OkStatus(); -} - } // namespace cel::internal diff --git a/internal/serialize.h b/internal/serialize.h index c915d41b2..fc5d0d745 100644 --- a/internal/serialize.h +++ b/internal/serialize.h @@ -22,7 +22,6 @@ #include "absl/strings/cord.h" #include "absl/strings/string_view.h" #include "absl/time/time.h" -#include "common/json.h" namespace cel::internal { @@ -57,14 +56,6 @@ absl::Status SerializeFloatValue(float value, absl::Cord& serialized_value); absl::Status SerializeDoubleValue(double value, absl::Cord& serialized_value); -absl::Status SerializeValue(const Json& value, absl::Cord& serialized_value); - -absl::Status SerializeListValue(const JsonArray& value, - absl::Cord& serialized_value); - -absl::Status SerializeStruct(const JsonObject& value, - absl::Cord& serialized_value); - size_t SerializedDurationSize(absl::Duration value); size_t SerializedTimestampSize(absl::Time value); @@ -91,12 +82,6 @@ size_t SerializedFloatValueSize(float value); size_t SerializedDoubleValueSize(double value); -size_t SerializedValueSize(const Json& value); - -size_t SerializedListValueSize(const JsonArray& value); - -size_t SerializedStructSize(const JsonObject& value); - } // namespace cel::internal #endif // THIRD_PARTY_CEL_CPP_INTERNAL_SERIALIZE_H_