1717#include < cstddef>
1818#include < cstdint>
1919#include < limits>
20+ #include < optional>
2021#include < string>
2122#include < type_traits>
2223#include < utility>
3132#include " absl/base/optimization.h"
3233#include " absl/functional/overload.h"
3334#include " absl/log/absl_check.h"
35+ #include " absl/log/absl_log.h"
3436#include " absl/status/status.h"
3537#include " absl/status/statusor.h"
3638#include " absl/strings/cord.h"
5052#include " internal/well_known_types.h"
5153#include " google/protobuf/arena.h"
5254#include " google/protobuf/descriptor.h"
55+ #include " google/protobuf/json/json.h"
5356#include " google/protobuf/message.h"
5457#include " google/protobuf/message_lite.h"
5558
@@ -79,6 +82,8 @@ using google::protobuf::Descriptor;
7982using google::protobuf::DescriptorPool;
8083using google::protobuf::Message;
8184using google::protobuf::MessageFactory;
85+ using google::protobuf::json::MessageToJsonString;
86+ using google::protobuf::json::PrintOptions;
8287
8388// kMaxIntJSON is defined as the Number.MAX_SAFE_INTEGER value per EcmaScript 6.
8489constexpr int64_t kMaxIntJSON = (1ll << 53 ) - 1 ;
@@ -98,6 +103,35 @@ static bool IsJSONSafe(uint64_t i) {
98103 return i <= static_cast <uint64_t >(kMaxIntJSON );
99104}
100105
106+ static bool IsEmptyProto (const google::protobuf::Descriptor* descriptor) {
107+ return descriptor->full_name () == " google.protobuf.Empty" ;
108+ }
109+
110+ static bool IsFieldMaskProto (const google::protobuf::Descriptor* descriptor) {
111+ return descriptor->full_name () == " google.protobuf.FieldMask" ;
112+ }
113+
114+ static std::optional<std::string> GetFieldMaskJsonString (
115+ const google::protobuf::Message& message) {
116+ // TODO(b/540507668): Refactor to pipe descriptor_pool through
117+ // ValueFromValue to use internal::MessageToJson.
118+ PrintOptions json_options;
119+ std::string json_str;
120+ auto status = MessageToJsonString (message, &json_str, json_options);
121+ if (!status.ok ()) {
122+ ABSL_LOG (ERROR ) << " Failed to convert FieldMask to JSON: " << status;
123+ return std::nullopt ;
124+ }
125+ // If JSON marshalling is correct, we know we'll always get a plain
126+ // JSON string value and it shouldn't contain any escapes that we need
127+ // to interpret.
128+ if (json_str.size () >= 2 && json_str.front () == ' "' &&
129+ json_str.back () == ' "' ) {
130+ return json_str.substr (1 , json_str.size () - 2 );
131+ }
132+ return json_str;
133+ }
134+
101135// Map implementation wrapping google.protobuf.ListValue
102136class DynamicList : public CelList {
103137 public:
@@ -1079,6 +1113,23 @@ google::protobuf::Message* ValueFromValue(google::protobuf::Message* message, co
10791113 return message;
10801114 }
10811115 } break ;
1116+ case CelValue::Type::kMessage : {
1117+ const google::protobuf::Message* message_ptr = value.MessageOrDie ();
1118+ if (IsEmptyProto (message_ptr->GetDescriptor ())) {
1119+ reflection.MutableStructValue (message);
1120+ return message;
1121+ }
1122+ if (IsFieldMaskProto (message_ptr->GetDescriptor ())) {
1123+ std::optional<std::string> fm_str =
1124+ GetFieldMaskJsonString (*message_ptr);
1125+ if (fm_str.has_value ()) {
1126+ reflection.SetStringValue (message, *fm_str);
1127+ return message;
1128+ }
1129+ return nullptr ;
1130+ }
1131+ return nullptr ;
1132+ } break ;
10821133 case CelValue::Type::kNullType :
10831134 reflection.SetNullValue (message);
10841135 return message;
@@ -1229,6 +1280,23 @@ bool ValueFromValue(Value* json, const CelValue& value, google::protobuf::Arena*
12291280 return ListFromValue (json->mutable_list_value (), value, arena);
12301281 case CelValue::Type::kMap :
12311282 return StructFromValue (json->mutable_struct_value (), value, arena);
1283+ case CelValue::Type::kMessage : {
1284+ const google::protobuf::Message* message_ptr = value.MessageOrDie ();
1285+ if (IsEmptyProto (message_ptr->GetDescriptor ())) {
1286+ json->mutable_struct_value ();
1287+ return true ;
1288+ }
1289+ if (IsFieldMaskProto (message_ptr->GetDescriptor ())) {
1290+ std::optional<std::string> fm_str =
1291+ GetFieldMaskJsonString (*message_ptr);
1292+ if (fm_str.has_value ()) {
1293+ json->set_string_value (*fm_str);
1294+ return true ;
1295+ }
1296+ return false ;
1297+ }
1298+ return false ;
1299+ }
12321300 case CelValue::Type::kNullType :
12331301 json->set_null_value (protobuf::NULL_VALUE );
12341302 return true ;
@@ -1254,7 +1322,7 @@ google::protobuf::Message* AnyFromValue(const google::protobuf::Message* prototy
12541322 case CelValue::Type::kBytes : {
12551323 BytesValue v;
12561324 type_name = v.GetTypeName ();
1257- v.set_value (std::string ( value.BytesOrDie ().value () ));
1325+ v.set_value (value.BytesOrDie ().value ());
12581326 payload = v.SerializeAsCord ();
12591327 } break ;
12601328 case CelValue::Type::kDouble : {
0 commit comments