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,7 +82,8 @@ using google::protobuf::Descriptor;
7982using google::protobuf::DescriptorPool;
8083using google::protobuf::Message;
8184using google::protobuf::MessageFactory;
82-
85+ using google::protobuf::json::MessageToJsonString;
86+ using google::protobuf::json::PrintOptions;
8387// kMaxIntJSON is defined as the Number.MAX_SAFE_INTEGER value per EcmaScript 6.
8488constexpr int64_t kMaxIntJSON = (1ll << 53 ) - 1 ;
8589
@@ -98,6 +102,27 @@ static bool IsJSONSafe(uint64_t i) {
98102 return i <= static_cast <uint64_t >(kMaxIntJSON );
99103}
100104
105+ static std::optional<std::string> GetFieldMaskJsonString (
106+ const google::protobuf::Message& message) {
107+ // TODO(b/540507668): Refactor to pipe descriptor_pool through
108+ // ValueFromValue to use internal::MessageToJson.
109+ PrintOptions json_options;
110+ std::string json_str;
111+ auto status = MessageToJsonString (message, &json_str, json_options);
112+ if (!status.ok ()) {
113+ ABSL_LOG (ERROR ) << " Failed to convert FieldMask to JSON: " << status;
114+ return std::nullopt ;
115+ }
116+ // If JSON marshalling is correct, we know we'll always get a plain
117+ // JSON string value and it shouldn't contain any escapes that we need
118+ // to interpret.
119+ if (json_str.size () >= 2 && json_str.front () == ' "' &&
120+ json_str.back () == ' "' ) {
121+ return json_str.substr (1 , json_str.size () - 2 );
122+ }
123+ return json_str;
124+ }
125+
101126// Map implementation wrapping google.protobuf.ListValue
102127class DynamicList : public CelList {
103128 public:
@@ -1079,6 +1104,20 @@ google::protobuf::Message* ValueFromValue(google::protobuf::Message* message, co
10791104 return message;
10801105 }
10811106 } break ;
1107+ case CelValue::Type::kMessage : {
1108+ const google::protobuf::Message* message_ptr = value.MessageOrDie ();
1109+ if (message_ptr->GetDescriptor ()->full_name () ==
1110+ " google.protobuf.FieldMask" ) {
1111+ std::optional<std::string> fm_str =
1112+ GetFieldMaskJsonString (*message_ptr);
1113+ if (fm_str.has_value ()) {
1114+ reflection.SetStringValue (message, *fm_str);
1115+ return message;
1116+ }
1117+ return nullptr ;
1118+ }
1119+ return nullptr ;
1120+ } break ;
10821121 case CelValue::Type::kNullType :
10831122 reflection.SetNullValue (message);
10841123 return message;
@@ -1229,6 +1268,20 @@ bool ValueFromValue(Value* json, const CelValue& value, google::protobuf::Arena*
12291268 return ListFromValue (json->mutable_list_value (), value, arena);
12301269 case CelValue::Type::kMap :
12311270 return StructFromValue (json->mutable_struct_value (), value, arena);
1271+ case CelValue::Type::kMessage : {
1272+ const google::protobuf::Message* message_ptr = value.MessageOrDie ();
1273+ if (message_ptr->GetDescriptor ()->full_name () ==
1274+ " google.protobuf.FieldMask" ) {
1275+ std::optional<std::string> fm_str =
1276+ GetFieldMaskJsonString (*message_ptr);
1277+ if (fm_str.has_value ()) {
1278+ json->set_string_value (*fm_str);
1279+ return true ;
1280+ }
1281+ return false ;
1282+ }
1283+ return false ;
1284+ }
12321285 case CelValue::Type::kNullType :
12331286 json->set_null_value (protobuf::NULL_VALUE );
12341287 return true ;
@@ -1254,7 +1307,7 @@ google::protobuf::Message* AnyFromValue(const google::protobuf::Message* prototy
12541307 case CelValue::Type::kBytes : {
12551308 BytesValue v;
12561309 type_name = v.GetTypeName ();
1257- v.set_value (std::string ( value.BytesOrDie ().value () ));
1310+ v.set_value (value.BytesOrDie ().value ());
12581311 payload = v.SerializeAsCord ();
12591312 } break ;
12601313 case CelValue::Type::kDouble : {
@@ -1280,7 +1333,7 @@ google::protobuf::Message* AnyFromValue(const google::protobuf::Message* prototy
12801333 case CelValue::Type::kString : {
12811334 StringValue v;
12821335 type_name = v.GetTypeName ();
1283- v.set_value (std::string ( value.StringOrDie ().value () ));
1336+ v.set_value (value.StringOrDie ().value ());
12841337 payload = v.SerializeAsCord ();
12851338 } break ;
12861339 case CelValue::Type::kTimestamp : {
0 commit comments