diff options
author | Anton Samokhvalov <pg83@yandex.ru> | 2022-02-10 16:45:15 +0300 |
---|---|---|
committer | Daniil Cherednik <dcherednik@yandex-team.ru> | 2022-02-10 16:45:15 +0300 |
commit | 72cb13b4aff9bc9cf22e49251bc8fd143f82538f (patch) | |
tree | da2c34829458c7d4e74bdfbdf85dff449e9e7fb8 /library/cpp/protobuf | |
parent | 778e51ba091dc39e7b7fcab2b9cf4dbedfb6f2b5 (diff) | |
download | ydb-72cb13b4aff9bc9cf22e49251bc8fd143f82538f.tar.gz |
Restoring authorship annotation for Anton Samokhvalov <pg83@yandex.ru>. Commit 1 of 2.
Diffstat (limited to 'library/cpp/protobuf')
47 files changed, 3717 insertions, 3717 deletions
diff --git a/library/cpp/protobuf/json/config.h b/library/cpp/protobuf/json/config.h index dc84fb4d5d..3bf0874360 100644 --- a/library/cpp/protobuf/json/config.h +++ b/library/cpp/protobuf/json/config.h @@ -9,16 +9,16 @@ #include <functional> namespace NProtobufJson { - struct TProto2JsonConfig { - using TSelf = TProto2JsonConfig; + struct TProto2JsonConfig { + using TSelf = TProto2JsonConfig; - bool FormatOutput = false; + bool FormatOutput = false; - enum MissingKeyMode { + enum MissingKeyMode { // Skip missing keys - MissingKeySkip = 0, + MissingKeySkip = 0, // Fill missing keys with json null value. - MissingKeyNull, + MissingKeyNull, // Use default value in any case. // If default value is not explicitly defined, use default type value: // i.e. 0 for integers, "" for strings @@ -29,31 +29,31 @@ namespace NProtobufJson { // Throw exception if required field is empty. // For repeated keys, same as MissingKeySkip MissingKeyExplicitDefaultThrowRequired - }; - MissingKeyMode MissingSingleKeyMode = MissingKeySkip; - MissingKeyMode MissingRepeatedKeyMode = MissingKeySkip; - - /// Add null value for missing fields (false by default). - bool AddMissingFields = false; - - enum EnumValueMode { - EnumNumber = 0, // default - EnumName, - EnumFullName, - EnumNameLowerCase, - EnumFullNameLowerCase, - }; - EnumValueMode EnumMode = EnumNumber; - - enum FldNameMode { - FieldNameOriginalCase = 0, // default - FieldNameLowerCase, - FieldNameUpperCase, - FieldNameCamelCase, + }; + MissingKeyMode MissingSingleKeyMode = MissingKeySkip; + MissingKeyMode MissingRepeatedKeyMode = MissingKeySkip; + + /// Add null value for missing fields (false by default). + bool AddMissingFields = false; + + enum EnumValueMode { + EnumNumber = 0, // default + EnumName, + EnumFullName, + EnumNameLowerCase, + EnumFullNameLowerCase, + }; + EnumValueMode EnumMode = EnumNumber; + + enum FldNameMode { + FieldNameOriginalCase = 0, // default + FieldNameLowerCase, + FieldNameUpperCase, + FieldNameCamelCase, FieldNameSnakeCase, // ABC -> a_b_c, UserID -> user_i_d FieldNameSnakeCaseDense // ABC -> abc, UserID -> user_id - }; - FldNameMode FieldNameMode = FieldNameOriginalCase; + }; + FldNameMode FieldNameMode = FieldNameOriginalCase; enum ExtFldNameMode { ExtFldNameFull = 0, // default, field.full_name() @@ -61,104 +61,104 @@ namespace NProtobufJson { }; ExtFldNameMode ExtensionFieldNameMode = ExtFldNameFull; - /// Use 'json_name' protobuf option for field name, mutually exclusive - /// with FieldNameMode. - bool UseJsonName = false; + /// Use 'json_name' protobuf option for field name, mutually exclusive + /// with FieldNameMode. + bool UseJsonName = false; - /// Transforms will be applied only to string values (== protobuf fields of string / bytes type). - /// yajl_encode_string will be used if no transforms are specified. - TVector<TStringTransformPtr> StringTransforms; + /// Transforms will be applied only to string values (== protobuf fields of string / bytes type). + /// yajl_encode_string will be used if no transforms are specified. + TVector<TStringTransformPtr> StringTransforms; - /// Print map as object, otherwise print it as array of key/value objects - bool MapAsObject = false; + /// Print map as object, otherwise print it as array of key/value objects + bool MapAsObject = false; /// Stringify long integers which are not exactly representable by float or double values - enum EStringifyLongNumbersMode { - StringifyLongNumbersNever = 0, // default - StringifyLongNumbersForFloat, - StringifyLongNumbersForDouble, - }; - EStringifyLongNumbersMode StringifyLongNumbers = StringifyLongNumbersNever; + enum EStringifyLongNumbersMode { + StringifyLongNumbersNever = 0, // default + StringifyLongNumbersForFloat, + StringifyLongNumbersForDouble, + }; + EStringifyLongNumbersMode StringifyLongNumbers = StringifyLongNumbersNever; - /// Custom field names generator. - TNameGenerator NameGenerator = {}; + /// Custom field names generator. + TNameGenerator NameGenerator = {}; - /// Custom enum values generator. - TEnumValueGenerator EnumValueGenerator = {}; + /// Custom enum values generator. + TEnumValueGenerator EnumValueGenerator = {}; bool WriteNanAsString = false; - TSelf& SetFormatOutput(bool format) { - FormatOutput = format; - return *this; - } - - TSelf& SetMissingSingleKeyMode(MissingKeyMode mode) { - MissingSingleKeyMode = mode; - return *this; - } - - TSelf& SetMissingRepeatedKeyMode(MissingKeyMode mode) { - MissingRepeatedKeyMode = mode; - return *this; - } - - TSelf& SetAddMissingFields(bool add) { - AddMissingFields = add; - return *this; - } - - TSelf& SetEnumMode(EnumValueMode mode) { - EnumMode = mode; - return *this; - } - - TSelf& SetFieldNameMode(FldNameMode mode) { - Y_ENSURE(mode == FieldNameOriginalCase || !UseJsonName, "FieldNameMode and UseJsonName are mutually exclusive"); - FieldNameMode = mode; - return *this; - } - - TSelf& SetUseJsonName(bool jsonName) { - Y_ENSURE(!jsonName || FieldNameMode == FieldNameOriginalCase, "FieldNameMode and UseJsonName are mutually exclusive"); - UseJsonName = jsonName; - return *this; - } + TSelf& SetFormatOutput(bool format) { + FormatOutput = format; + return *this; + } + + TSelf& SetMissingSingleKeyMode(MissingKeyMode mode) { + MissingSingleKeyMode = mode; + return *this; + } + + TSelf& SetMissingRepeatedKeyMode(MissingKeyMode mode) { + MissingRepeatedKeyMode = mode; + return *this; + } + + TSelf& SetAddMissingFields(bool add) { + AddMissingFields = add; + return *this; + } + + TSelf& SetEnumMode(EnumValueMode mode) { + EnumMode = mode; + return *this; + } + + TSelf& SetFieldNameMode(FldNameMode mode) { + Y_ENSURE(mode == FieldNameOriginalCase || !UseJsonName, "FieldNameMode and UseJsonName are mutually exclusive"); + FieldNameMode = mode; + return *this; + } + + TSelf& SetUseJsonName(bool jsonName) { + Y_ENSURE(!jsonName || FieldNameMode == FieldNameOriginalCase, "FieldNameMode and UseJsonName are mutually exclusive"); + UseJsonName = jsonName; + return *this; + } TSelf& SetExtensionFieldNameMode(ExtFldNameMode mode) { ExtensionFieldNameMode = mode; return *this; } - TSelf& AddStringTransform(TStringTransformPtr transform) { - StringTransforms.push_back(transform); - return *this; - } + TSelf& AddStringTransform(TStringTransformPtr transform) { + StringTransforms.push_back(transform); + return *this; + } - TSelf& SetMapAsObject(bool value) { - MapAsObject = value; - return *this; - } + TSelf& SetMapAsObject(bool value) { + MapAsObject = value; + return *this; + } - TSelf& SetStringifyLongNumbers(EStringifyLongNumbersMode stringify) { - StringifyLongNumbers = stringify; - return *this; - } + TSelf& SetStringifyLongNumbers(EStringifyLongNumbersMode stringify) { + StringifyLongNumbers = stringify; + return *this; + } - TSelf& SetNameGenerator(TNameGenerator callback) { - NameGenerator = callback; - return *this; - } + TSelf& SetNameGenerator(TNameGenerator callback) { + NameGenerator = callback; + return *this; + } - TSelf& SetEnumValueGenerator(TEnumValueGenerator callback) { - EnumValueGenerator = callback; - return *this; - } + TSelf& SetEnumValueGenerator(TEnumValueGenerator callback) { + EnumValueGenerator = callback; + return *this; + } TSelf& SetWriteNanAsString(bool value) { WriteNanAsString = value; return *this; } - }; + }; -} +} diff --git a/library/cpp/protobuf/json/field_option.h b/library/cpp/protobuf/json/field_option.h index c8a8bfbff5..6241452b6a 100644 --- a/library/cpp/protobuf/json/field_option.h +++ b/library/cpp/protobuf/json/field_option.h @@ -5,36 +5,36 @@ #include <google/protobuf/message.h> namespace NProtobufJson { - // Functor that defines whether given field has some option set to true - // - // Example: - // message T { - // optional stroka some_field = 1 [(some_option) = true]; - // } - // - template <typename TFieldOptionExtensionId> - class TFieldOptionFunctor { - public: - TFieldOptionFunctor(const TFieldOptionExtensionId& option, bool positive = true) - : Option(option) - , Positive(positive) - { - } + // Functor that defines whether given field has some option set to true + // + // Example: + // message T { + // optional stroka some_field = 1 [(some_option) = true]; + // } + // + template <typename TFieldOptionExtensionId> + class TFieldOptionFunctor { + public: + TFieldOptionFunctor(const TFieldOptionExtensionId& option, bool positive = true) + : Option(option) + , Positive(positive) + { + } - bool operator()(const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor* field) const { - const NProtoBuf::FieldOptions& opt = field->options(); - const bool val = opt.GetExtension(Option); - return Positive ? val : !val; - } + bool operator()(const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor* field) const { + const NProtoBuf::FieldOptions& opt = field->options(); + const bool val = opt.GetExtension(Option); + return Positive ? val : !val; + } - private: - const TFieldOptionExtensionId& Option; - bool Positive; - }; - - template <typename TFieldOptionExtensionId> - TFieldOptionFunctor<TFieldOptionExtensionId> MakeFieldOptionFunctor(const TFieldOptionExtensionId& option, bool positive = true) { - return TFieldOptionFunctor<TFieldOptionExtensionId>(option, positive); + private: + const TFieldOptionExtensionId& Option; + bool Positive; + }; + + template <typename TFieldOptionExtensionId> + TFieldOptionFunctor<TFieldOptionExtensionId> MakeFieldOptionFunctor(const TFieldOptionExtensionId& option, bool positive = true) { + return TFieldOptionFunctor<TFieldOptionExtensionId>(option, positive); } } diff --git a/library/cpp/protobuf/json/filter.h b/library/cpp/protobuf/json/filter.h index 9a3ddb54fe..eced62c01a 100644 --- a/library/cpp/protobuf/json/filter.h +++ b/library/cpp/protobuf/json/filter.h @@ -10,39 +10,39 @@ #include <functional> namespace NProtobufJson { - template <typename TBasePrinter = TProto2JsonPrinter> // TBasePrinter is assumed to be a TProto2JsonPrinter descendant - class TFilteringPrinter: public TBasePrinter { - public: - using TFieldPredicate = std::function<bool(const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor*)>; - - template <typename... TArgs> - TFilteringPrinter(TFieldPredicate isPrinted, TArgs&&... args) - : TBasePrinter(std::forward<TArgs>(args)...) - , IsPrinted(std::move(isPrinted)) - { - } - - virtual void PrintField(const NProtoBuf::Message& proto, - const NProtoBuf::FieldDescriptor& field, - IJsonOutput& json, - TStringBuf key) override { - if (key || IsPrinted(proto, &field)) - TBasePrinter::PrintField(proto, field, json, key); - } - - private: - TFieldPredicate IsPrinted; - }; - - inline void PrintWithFilter(const NProtoBuf::Message& msg, TFilteringPrinter<>::TFieldPredicate filter, IJsonOutput& output, const TProto2JsonConfig& config = TProto2JsonConfig()) { - TFilteringPrinter<> printer(std::move(filter), config); - printer.Print(msg, output); + template <typename TBasePrinter = TProto2JsonPrinter> // TBasePrinter is assumed to be a TProto2JsonPrinter descendant + class TFilteringPrinter: public TBasePrinter { + public: + using TFieldPredicate = std::function<bool(const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor*)>; + + template <typename... TArgs> + TFilteringPrinter(TFieldPredicate isPrinted, TArgs&&... args) + : TBasePrinter(std::forward<TArgs>(args)...) + , IsPrinted(std::move(isPrinted)) + { + } + + virtual void PrintField(const NProtoBuf::Message& proto, + const NProtoBuf::FieldDescriptor& field, + IJsonOutput& json, + TStringBuf key) override { + if (key || IsPrinted(proto, &field)) + TBasePrinter::PrintField(proto, field, json, key); + } + + private: + TFieldPredicate IsPrinted; + }; + + inline void PrintWithFilter(const NProtoBuf::Message& msg, TFilteringPrinter<>::TFieldPredicate filter, IJsonOutput& output, const TProto2JsonConfig& config = TProto2JsonConfig()) { + TFilteringPrinter<> printer(std::move(filter), config); + printer.Print(msg, output); } - inline TString PrintWithFilter(const NProtoBuf::Message& msg, TFilteringPrinter<>::TFieldPredicate filter, const TProto2JsonConfig& config = TProto2JsonConfig()) { - TString ret; - PrintWithFilter(msg, std::move(filter), *CreateJsonMapOutput(ret, config), config); - return ret; + inline TString PrintWithFilter(const NProtoBuf::Message& msg, TFilteringPrinter<>::TFieldPredicate filter, const TProto2JsonConfig& config = TProto2JsonConfig()) { + TString ret; + PrintWithFilter(msg, std::move(filter), *CreateJsonMapOutput(ret, config), config); + return ret; } } diff --git a/library/cpp/protobuf/json/inline.h b/library/cpp/protobuf/json/inline.h index e2d7bb6ef0..e5b0980227 100644 --- a/library/cpp/protobuf/json/inline.h +++ b/library/cpp/protobuf/json/inline.h @@ -48,68 +48,68 @@ #include <functional> namespace NProtobufJson { - template <typename TBasePrinter = TProto2JsonPrinter> // TBasePrinter is assumed to be a TProto2JsonPrinter descendant - class TInliningPrinter: public TBasePrinter { - public: - using TFieldPredicate = std::function<bool(const NProtoBuf::Message&, - const NProtoBuf::FieldDescriptor*)>; - - template <typename... TArgs> - TInliningPrinter(TFieldPredicate isInlined, TArgs&&... args) - : TBasePrinter(std::forward<TArgs>(args)...) - , IsInlined(std::move(isInlined)) - { - } - - virtual void PrintField(const NProtoBuf::Message& proto, - const NProtoBuf::FieldDescriptor& field, - IJsonOutput& json, - TStringBuf key) override { - const NProtoBuf::TConstField f(proto, &field); - if (!key && IsInlined(proto, &field) && ShouldPrint(f)) { - key = this->MakeKey(field); - json.WriteKey(key); - if (!field.is_repeated()) { - json.WriteRawJson(f.Get<TString>()); - } else { - json.BeginList(); - for (size_t i = 0, sz = f.Size(); i < sz; ++i) - json.WriteRawJson(f.Get<TString>(i)); - json.EndList(); - } + template <typename TBasePrinter = TProto2JsonPrinter> // TBasePrinter is assumed to be a TProto2JsonPrinter descendant + class TInliningPrinter: public TBasePrinter { + public: + using TFieldPredicate = std::function<bool(const NProtoBuf::Message&, + const NProtoBuf::FieldDescriptor*)>; + + template <typename... TArgs> + TInliningPrinter(TFieldPredicate isInlined, TArgs&&... args) + : TBasePrinter(std::forward<TArgs>(args)...) + , IsInlined(std::move(isInlined)) + { + } + + virtual void PrintField(const NProtoBuf::Message& proto, + const NProtoBuf::FieldDescriptor& field, + IJsonOutput& json, + TStringBuf key) override { + const NProtoBuf::TConstField f(proto, &field); + if (!key && IsInlined(proto, &field) && ShouldPrint(f)) { + key = this->MakeKey(field); + json.WriteKey(key); + if (!field.is_repeated()) { + json.WriteRawJson(f.Get<TString>()); + } else { + json.BeginList(); + for (size_t i = 0, sz = f.Size(); i < sz; ++i) + json.WriteRawJson(f.Get<TString>(i)); + json.EndList(); + } } else { - TBasePrinter::PrintField(proto, field, json, key); + TBasePrinter::PrintField(proto, field, json, key); } + } + + private: + bool ShouldPrint(const NProtoBuf::TConstField& f) const { + if (!f.IsString()) + ythrow yexception() << "TInliningPrinter: json field " + << f.Field()->name() << " should be a string"; + + if (f.HasValue()) + return true; + + // we may want write default value for given field in case of its absence + const auto& cfg = this->GetConfig(); + return (f.Field()->is_repeated() ? cfg.MissingRepeatedKeyMode : cfg.MissingSingleKeyMode) == TProto2JsonConfig::MissingKeyDefault; } - private: - bool ShouldPrint(const NProtoBuf::TConstField& f) const { - if (!f.IsString()) - ythrow yexception() << "TInliningPrinter: json field " - << f.Field()->name() << " should be a string"; - - if (f.HasValue()) - return true; - - // we may want write default value for given field in case of its absence - const auto& cfg = this->GetConfig(); - return (f.Field()->is_repeated() ? cfg.MissingRepeatedKeyMode : cfg.MissingSingleKeyMode) == TProto2JsonConfig::MissingKeyDefault; - } - - private: - TFieldPredicate IsInlined; - }; + private: + TFieldPredicate IsInlined; + }; - inline void PrintInlined(const NProtoBuf::Message& msg, TInliningPrinter<>::TFieldPredicate isInlined, IJsonOutput& output, const TProto2JsonConfig& config = TProto2JsonConfig()) { - TInliningPrinter<> printer(std::move(isInlined), config); - printer.Print(msg, output); - } + inline void PrintInlined(const NProtoBuf::Message& msg, TInliningPrinter<>::TFieldPredicate isInlined, IJsonOutput& output, const TProto2JsonConfig& config = TProto2JsonConfig()) { + TInliningPrinter<> printer(std::move(isInlined), config); + printer.Print(msg, output); + } - inline TString PrintInlined(const NProtoBuf::Message& msg, TInliningPrinter<>::TFieldPredicate isInlined, const TProto2JsonConfig& config = TProto2JsonConfig()) { - TString ret; - PrintInlined(msg, std::move(isInlined), *CreateJsonMapOutput(ret, config), config); - return ret; + inline TString PrintInlined(const NProtoBuf::Message& msg, TInliningPrinter<>::TFieldPredicate isInlined, const TProto2JsonConfig& config = TProto2JsonConfig()) { + TString ret; + PrintInlined(msg, std::move(isInlined), *CreateJsonMapOutput(ret, config), config); + return ret; } } diff --git a/library/cpp/protobuf/json/json2proto.cpp b/library/cpp/protobuf/json/json2proto.cpp index 640c10f5a5..4eaa035ce4 100644 --- a/library/cpp/protobuf/json/json2proto.cpp +++ b/library/cpp/protobuf/json/json2proto.cpp @@ -35,7 +35,7 @@ } static TString GetFieldName(const google::protobuf::FieldDescriptor& field, - const NProtobufJson::TJson2ProtoConfig& config) { + const NProtobufJson::TJson2ProtoConfig& config) { if (config.NameGenerator) { return config.NameGenerator(field); } @@ -81,7 +81,7 @@ static void JsonString2Field(const NJson::TJsonValue& json, google::protobuf::Message& proto, const google::protobuf::FieldDescriptor& field, - const NProtobufJson::TJson2ProtoConfig& config) { + const NProtobufJson::TJson2ProtoConfig& config) { using namespace google::protobuf; const Reflection* reflection = proto.GetReflection(); @@ -172,7 +172,7 @@ Json2SingleField(const NJson::TJsonValue& json, google::protobuf::Message& proto, const google::protobuf::FieldDescriptor& field, const NProtobufJson::TJson2ProtoConfig& config, - bool isMapValue = false) { + bool isMapValue = false) { using namespace google::protobuf; const Reflection* reflection = proto.GetReflection(); @@ -181,7 +181,7 @@ Json2SingleField(const NJson::TJsonValue& json, TString name; if (!isMapValue) { name = GetFieldName(field, config); - if (!json.Has(name) || json[name].GetType() == NJson::JSON_UNDEFINED || json[name].GetType() == NJson::JSON_NULL) { + if (!json.Has(name) || json[name].GetType() == NJson::JSON_UNDEFINED || json[name].GetType() == NJson::JSON_NULL) { if (field.is_required() && !field.has_default_value() && !reflection->HasField(proto, &field) && config.CheckRequiredFields) { ythrow yexception() << "JSON has no field for required field " << name << "."; @@ -202,27 +202,27 @@ Json2SingleField(const NJson::TJsonValue& json, JSON_TO_FIELD(CPPTYPE_FLOAT, field.name(), fieldJson, IsDouble, SetFloat, GetDouble); JSON_TO_FIELD(CPPTYPE_BOOL, field.name(), fieldJson, IsBoolean, SetBool, GetBoolean); - case FieldDescriptor::CPPTYPE_STRING: { - JsonString2Field(fieldJson, proto, field, config); - break; - } + case FieldDescriptor::CPPTYPE_STRING: { + JsonString2Field(fieldJson, proto, field, config); + break; + } - case FieldDescriptor::CPPTYPE_ENUM: { + case FieldDescriptor::CPPTYPE_ENUM: { JsonEnum2Field(fieldJson, proto, field, config); - break; - } + break; + } - case FieldDescriptor::CPPTYPE_MESSAGE: { - Message* innerProto = reflection->MutableMessage(&proto, &field); - Y_ASSERT(!!innerProto); + case FieldDescriptor::CPPTYPE_MESSAGE: { + Message* innerProto = reflection->MutableMessage(&proto, &field); + Y_ASSERT(!!innerProto); NProtobufJson::MergeJson2Proto(fieldJson, *innerProto, config); - break; - } + break; + } - default: - ythrow yexception() << "Unknown protobuf field type: " - << static_cast<int>(field.cpp_type()) << "."; + default: + ythrow yexception() << "Unknown protobuf field type: " + << static_cast<int>(field.cpp_type()) << "."; } } @@ -315,7 +315,7 @@ static void Json2RepeatedField(const NJson::TJsonValue& json, google::protobuf::Message& proto, const google::protobuf::FieldDescriptor& field, - const NProtobufJson::TJson2ProtoConfig& config) { + const NProtobufJson::TJson2ProtoConfig& config) { using namespace google::protobuf; TString name = GetFieldName(field, config); @@ -323,7 +323,7 @@ Json2RepeatedField(const NJson::TJsonValue& json, return; const NJson::TJsonValue& fieldJson = json[name]; - if (fieldJson.GetType() == NJson::JSON_UNDEFINED || fieldJson.GetType() == NJson::JSON_NULL) + if (fieldJson.GetType() == NJson::JSON_UNDEFINED || fieldJson.GetType() == NJson::JSON_NULL) return; bool isMap = fieldJson.GetType() == NJson::JSON_MAP; @@ -373,49 +373,49 @@ Json2RepeatedField(const NJson::TJsonValue& json, namespace NProtobufJson { void MergeJson2Proto(const NJson::TJsonValue& json, google::protobuf::Message& proto, const TJson2ProtoConfig& config) { - if (json.IsNull()) { - return; - } + if (json.IsNull()) { + return; + } - Y_ENSURE(json.IsMap(), "expected json map"); + Y_ENSURE(json.IsMap(), "expected json map"); - const google::protobuf::Descriptor* descriptor = proto.GetDescriptor(); - Y_ASSERT(!!descriptor); + const google::protobuf::Descriptor* descriptor = proto.GetDescriptor(); + Y_ASSERT(!!descriptor); - for (int f = 0, endF = descriptor->field_count(); f < endF; ++f) { - const google::protobuf::FieldDescriptor* field = descriptor->field(f); - Y_ASSERT(!!field); + for (int f = 0, endF = descriptor->field_count(); f < endF; ++f) { + const google::protobuf::FieldDescriptor* field = descriptor->field(f); + Y_ASSERT(!!field); - if (field->is_repeated()) { - Json2RepeatedField(json, proto, *field, config); - } else { - Json2SingleField(json, proto, *field, config); - } + if (field->is_repeated()) { + Json2RepeatedField(json, proto, *field, config); + } else { + Json2SingleField(json, proto, *field, config); + } } - if (!config.AllowUnknownFields) { - THashMap<TString, bool> knownFields; - for (int f = 0, endF = descriptor->field_count(); f < endF; ++f) { - const google::protobuf::FieldDescriptor* field = descriptor->field(f); - knownFields[GetFieldName(*field, config)] = 1; - } - for (const auto& f : json.GetMap()) { + if (!config.AllowUnknownFields) { + THashMap<TString, bool> knownFields; + for (int f = 0, endF = descriptor->field_count(); f < endF; ++f) { + const google::protobuf::FieldDescriptor* field = descriptor->field(f); + knownFields[GetFieldName(*field, config)] = 1; + } + for (const auto& f : json.GetMap()) { Y_ENSURE(knownFields.contains(f.first), "unknown field " << f.first); - } + } } } void MergeJson2Proto(const TStringBuf& json, google::protobuf::Message& proto, const TJson2ProtoConfig& config) { - NJson::TJsonReaderConfig jsonCfg; - jsonCfg.DontValidateUtf8 = true; + NJson::TJsonReaderConfig jsonCfg; + jsonCfg.DontValidateUtf8 = true; jsonCfg.AllowComments = config.AllowComments; - NJson::TJsonValue jsonValue; - ReadJsonTree(json, &jsonCfg, &jsonValue, /* throwOnError = */ true); + NJson::TJsonValue jsonValue; + ReadJsonTree(json, &jsonCfg, &jsonValue, /* throwOnError = */ true); MergeJson2Proto(jsonValue, proto, config); - } - + } + void Json2Proto(const NJson::TJsonValue& json, google::protobuf::Message& proto, const TJson2ProtoConfig& config) { proto.Clear(); MergeJson2Proto(json, proto, config); diff --git a/library/cpp/protobuf/json/json2proto.h b/library/cpp/protobuf/json/json2proto.h index 4c33498dfa..44b05644c0 100644 --- a/library/cpp/protobuf/json/json2proto.h +++ b/library/cpp/protobuf/json/json2proto.h @@ -5,30 +5,30 @@ #include <library/cpp/json/json_reader.h> #include <library/cpp/json/json_value.h> - + #include <util/stream/input.h> -#include <util/stream/str.h> +#include <util/stream/str.h> #include <util/stream/mem.h> -namespace google { - namespace protobuf { - class Message; - } -} +namespace google { + namespace protobuf { + class Message; + } +} namespace NProtobufJson { - struct TJson2ProtoConfig { - using TSelf = TJson2ProtoConfig; + struct TJson2ProtoConfig { + using TSelf = TJson2ProtoConfig; using TValueVectorizer = std::function<NJson::TJsonValue::TArray(const NJson::TJsonValue& jsonValue)>; - enum FldNameMode { - FieldNameOriginalCase = 0, // default - FieldNameLowerCase, - FieldNameUpperCase, - FieldNameCamelCase, + enum FldNameMode { + FieldNameOriginalCase = 0, // default + FieldNameLowerCase, + FieldNameUpperCase, + FieldNameCamelCase, FieldNameSnakeCase, // ABC -> a_b_c, UserID -> user_i_d FieldNameSnakeCaseDense // ABC -> abc, UserID -> user_id - }; + }; enum EnumValueMode { EnumCaseSensetive = 0, // default @@ -36,37 +36,37 @@ namespace NProtobufJson { EnumSnakeCaseInsensitive }; - TSelf& SetFieldNameMode(FldNameMode mode) { - Y_ENSURE(mode == FieldNameOriginalCase || !UseJsonName, "FieldNameMode and UseJsonName are mutually exclusive"); - FieldNameMode = mode; - return *this; - } + TSelf& SetFieldNameMode(FldNameMode mode) { + Y_ENSURE(mode == FieldNameOriginalCase || !UseJsonName, "FieldNameMode and UseJsonName are mutually exclusive"); + FieldNameMode = mode; + return *this; + } - TSelf& SetUseJsonName(bool jsonName) { - Y_ENSURE(!jsonName || FieldNameMode == FieldNameOriginalCase, "FieldNameMode and UseJsonName are mutually exclusive"); - UseJsonName = jsonName; - return *this; - } + TSelf& SetUseJsonName(bool jsonName) { + Y_ENSURE(!jsonName || FieldNameMode == FieldNameOriginalCase, "FieldNameMode and UseJsonName are mutually exclusive"); + UseJsonName = jsonName; + return *this; + } - TSelf& AddStringTransform(TStringTransformPtr transform) { - StringTransforms.push_back(transform); - return *this; - } + TSelf& AddStringTransform(TStringTransformPtr transform) { + StringTransforms.push_back(transform); + return *this; + } - TSelf& SetCastFromString(bool cast) { - CastFromString = cast; - return *this; - } + TSelf& SetCastFromString(bool cast) { + CastFromString = cast; + return *this; + } TSelf& SetDoNotCastEmptyStrings(bool cast) { DoNotCastEmptyStrings = cast; return *this; } - TSelf& SetCastRobust(bool cast) { - CastRobust = cast; - return *this; - } + TSelf& SetCastRobust(bool cast) { + CastRobust = cast; + return *this; + } TSelf& SetMapAsObject(bool mapAsObject) { MapAsObject = mapAsObject; @@ -78,10 +78,10 @@ namespace NProtobufJson { return *this; } - TSelf& SetNameGenerator(TNameGenerator callback) { - NameGenerator = callback; - return *this; - } + TSelf& SetNameGenerator(TNameGenerator callback) { + NameGenerator = callback; + return *this; + } TSelf& SetEnumValueMode(EnumValueMode enumValueMode) { EnumValueMode = enumValueMode; @@ -104,34 +104,34 @@ namespace NProtobufJson { } FldNameMode FieldNameMode = FieldNameOriginalCase; - bool AllowUnknownFields = true; + bool AllowUnknownFields = true; - /// Use 'json_name' protobuf option for field name, mutually exclusive - /// with FieldNameMode. - bool UseJsonName = false; + /// Use 'json_name' protobuf option for field name, mutually exclusive + /// with FieldNameMode. + bool UseJsonName = false; - /// Transforms will be applied only to string values (== protobuf fields of string / bytes type). - TVector<TStringTransformPtr> StringTransforms; + /// Transforms will be applied only to string values (== protobuf fields of string / bytes type). + TVector<TStringTransformPtr> StringTransforms; - /// Cast string json values to protobuf field type - bool CastFromString = false; + /// Cast string json values to protobuf field type + bool CastFromString = false; /// Skip empty strings, instead casting from string into scalar types. /// I.e. empty string like default value for scalar types. bool DoNotCastEmptyStrings = false; - /// Cast all json values to protobuf field types - bool CastRobust = false; + /// Cast all json values to protobuf field types + bool CastRobust = false; - /// Consider map to be an object, otherwise consider it to be an array of key/value objects - bool MapAsObject = false; + /// Consider map to be an object, otherwise consider it to be an array of key/value objects + bool MapAsObject = false; - /// Throw exception if there is no required fields in json object. - bool CheckRequiredFields = true; + /// Throw exception if there is no required fields in json object. + bool CheckRequiredFields = true; /// Replace repeated fields content during merging bool ReplaceRepeatedFields = false; - /// Custom field names generator. - TNameGenerator NameGenerator = {}; + /// Custom field names generator. + TNameGenerator NameGenerator = {}; /// Enum value parsing mode. EnumValueMode EnumValueMode = EnumCaseSensetive; @@ -144,9 +144,9 @@ namespace NProtobufJson { /// Allow js-style comments (both // and /**/) bool AllowComments = false; - }; + }; - /// @throw yexception + /// @throw yexception void MergeJson2Proto(const NJson::TJsonValue& json, google::protobuf::Message& proto, const TJson2ProtoConfig& config = TJson2ProtoConfig()); @@ -161,62 +161,62 @@ namespace NProtobufJson { } /// @throw yexception - void Json2Proto(const NJson::TJsonValue& json, google::protobuf::Message& proto, - const TJson2ProtoConfig& config = TJson2ProtoConfig()); + void Json2Proto(const NJson::TJsonValue& json, google::protobuf::Message& proto, + const TJson2ProtoConfig& config = TJson2ProtoConfig()); - /// @throw yexception - void Json2Proto(const TStringBuf& json, google::protobuf::Message& proto, - const TJson2ProtoConfig& config = TJson2ProtoConfig()); + /// @throw yexception + void Json2Proto(const TStringBuf& json, google::protobuf::Message& proto, + const TJson2ProtoConfig& config = TJson2ProtoConfig()); - /// @throw yexception - inline void Json2Proto(const TString& json, google::protobuf::Message& proto, - const TJson2ProtoConfig& config = TJson2ProtoConfig()) { - Json2Proto(TStringBuf(json), proto, config); - } + /// @throw yexception + inline void Json2Proto(const TString& json, google::protobuf::Message& proto, + const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + Json2Proto(TStringBuf(json), proto, config); + } - /// @throw yexception + /// @throw yexception inline void Json2Proto(IInputStream& in, google::protobuf::Message& proto, const TJson2ProtoConfig& config = TJson2ProtoConfig()) { Json2Proto(TStringBuf(in.ReadAll()), proto, config); } /// @throw yexception - template <typename T> - T Json2Proto(IInputStream& in, const NJson::TJsonReaderConfig& readerConfig, - const TJson2ProtoConfig& config = TJson2ProtoConfig()) { - NJson::TJsonValue jsonValue; - NJson::ReadJsonTree(&in, &readerConfig, &jsonValue, true); - T protoValue; - Json2Proto(jsonValue, protoValue, config); - return protoValue; - } - - /// @throw yexception - template <typename T> - T Json2Proto(IInputStream& in, const TJson2ProtoConfig& config = TJson2ProtoConfig()) { - NJson::TJsonReaderConfig readerConfig; - readerConfig.DontValidateUtf8 = true; - return Json2Proto<T>(in, readerConfig, config); - } - - /// @throw yexception - template <typename T> - T Json2Proto(const TString& value, const TJson2ProtoConfig& config = TJson2ProtoConfig()) { - TStringInput in(value); - return Json2Proto<T>(in, config); - } - - /// @throw yexception - template <typename T> - T Json2Proto(const TStringBuf& value, const TJson2ProtoConfig& config = TJson2ProtoConfig()) { - TMemoryInput in(value); - return Json2Proto<T>(in, config); - } - - /// @throw yexception - template <typename T> - T Json2Proto(const char* ptr, const TJson2ProtoConfig& config = TJson2ProtoConfig()) { - return Json2Proto<T>(TStringBuf(ptr), config); - } + template <typename T> + T Json2Proto(IInputStream& in, const NJson::TJsonReaderConfig& readerConfig, + const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + NJson::TJsonValue jsonValue; + NJson::ReadJsonTree(&in, &readerConfig, &jsonValue, true); + T protoValue; + Json2Proto(jsonValue, protoValue, config); + return protoValue; + } + + /// @throw yexception + template <typename T> + T Json2Proto(IInputStream& in, const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + NJson::TJsonReaderConfig readerConfig; + readerConfig.DontValidateUtf8 = true; + return Json2Proto<T>(in, readerConfig, config); + } + + /// @throw yexception + template <typename T> + T Json2Proto(const TString& value, const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + TStringInput in(value); + return Json2Proto<T>(in, config); + } + + /// @throw yexception + template <typename T> + T Json2Proto(const TStringBuf& value, const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + TMemoryInput in(value); + return Json2Proto<T>(in, config); + } + + /// @throw yexception + template <typename T> + T Json2Proto(const char* ptr, const TJson2ProtoConfig& config = TJson2ProtoConfig()) { + return Json2Proto<T>(TStringBuf(ptr), config); + } } diff --git a/library/cpp/protobuf/json/json_output.h b/library/cpp/protobuf/json/json_output.h index df143af57a..8007909fda 100644 --- a/library/cpp/protobuf/json/json_output.h +++ b/library/cpp/protobuf/json/json_output.h @@ -4,76 +4,76 @@ #include <util/generic/strbuf.h> namespace NProtobufJson { - class IJsonOutput { - public: - template <typename T> - IJsonOutput& Write(const T& t) { - DoWrite(t); - return *this; - } - IJsonOutput& WriteNull() { - DoWriteNull(); - return *this; - } + class IJsonOutput { + public: + template <typename T> + IJsonOutput& Write(const T& t) { + DoWrite(t); + return *this; + } + IJsonOutput& WriteNull() { + DoWriteNull(); + return *this; + } - IJsonOutput& BeginList() { - DoBeginList(); - return *this; - } - IJsonOutput& EndList() { - DoEndList(); - return *this; - } + IJsonOutput& BeginList() { + DoBeginList(); + return *this; + } + IJsonOutput& EndList() { + DoEndList(); + return *this; + } - IJsonOutput& BeginObject() { - DoBeginObject(); - return *this; - } - IJsonOutput& WriteKey(const TStringBuf& key) { - DoWriteKey(key); - return *this; - } - IJsonOutput& EndObject() { - DoEndObject(); - return *this; - } + IJsonOutput& BeginObject() { + DoBeginObject(); + return *this; + } + IJsonOutput& WriteKey(const TStringBuf& key) { + DoWriteKey(key); + return *this; + } + IJsonOutput& EndObject() { + DoEndObject(); + return *this; + } - IJsonOutput& WriteRawJson(const TStringBuf& str) { - DoWriteRawJson(str); - return *this; - } + IJsonOutput& WriteRawJson(const TStringBuf& str) { + DoWriteRawJson(str); + return *this; + } - virtual ~IJsonOutput() { - } + virtual ~IJsonOutput() { + } - protected: - virtual void DoWrite(const TStringBuf& s) = 0; - virtual void DoWrite(const TString& s) = 0; - virtual void DoWrite(int i) = 0; - void DoWrite(long i) { - DoWrite(static_cast<long long>(i)); - } - virtual void DoWrite(long long i) = 0; - virtual void DoWrite(unsigned int i) = 0; - void DoWrite(unsigned long i) { - DoWrite(static_cast<unsigned long long>(i)); - } - virtual void DoWrite(unsigned long long i) = 0; - virtual void DoWrite(float f) = 0; - virtual void DoWrite(double f) = 0; - virtual void DoWrite(bool b) = 0; - virtual void DoWriteNull() = 0; + protected: + virtual void DoWrite(const TStringBuf& s) = 0; + virtual void DoWrite(const TString& s) = 0; + virtual void DoWrite(int i) = 0; + void DoWrite(long i) { + DoWrite(static_cast<long long>(i)); + } + virtual void DoWrite(long long i) = 0; + virtual void DoWrite(unsigned int i) = 0; + void DoWrite(unsigned long i) { + DoWrite(static_cast<unsigned long long>(i)); + } + virtual void DoWrite(unsigned long long i) = 0; + virtual void DoWrite(float f) = 0; + virtual void DoWrite(double f) = 0; + virtual void DoWrite(bool b) = 0; + virtual void DoWriteNull() = 0; - virtual void DoBeginList() = 0; - virtual void DoEndList() = 0; + virtual void DoBeginList() = 0; + virtual void DoEndList() = 0; - virtual void DoBeginObject() = 0; - virtual void DoWriteKey(const TStringBuf& key) = 0; - virtual void DoEndObject() = 0; + virtual void DoBeginObject() = 0; + virtual void DoWriteKey(const TStringBuf& key) = 0; + virtual void DoEndObject() = 0; - virtual void DoWriteRawJson(const TStringBuf& str) = 0; - }; + virtual void DoWriteRawJson(const TStringBuf& str) = 0; + }; - using TJsonMapOutputPtr = THolder<IJsonOutput>; + using TJsonMapOutputPtr = THolder<IJsonOutput>; -} +} diff --git a/library/cpp/protobuf/json/json_output_create.cpp b/library/cpp/protobuf/json/json_output_create.cpp index 378e4ea65a..7c84c97e76 100644 --- a/library/cpp/protobuf/json/json_output_create.cpp +++ b/library/cpp/protobuf/json/json_output_create.cpp @@ -5,28 +5,28 @@ #include "json_value_output.h" namespace NProtobufJson { - TJsonMapOutputPtr CreateJsonMapOutput(IOutputStream& out, const NJson::TJsonWriterConfig& config) { + TJsonMapOutputPtr CreateJsonMapOutput(IOutputStream& out, const NJson::TJsonWriterConfig& config) { return MakeHolder<TJsonWriterOutput>(&out, config); - } + } - TJsonMapOutputPtr CreateJsonMapOutput(NJson::TJsonWriter& writer) { + TJsonMapOutputPtr CreateJsonMapOutput(NJson::TJsonWriter& writer) { return MakeHolder<TBaseJsonWriterOutput>(writer); - } + } - TJsonMapOutputPtr CreateJsonMapOutput(TString& str, const TProto2JsonConfig& config) { + TJsonMapOutputPtr CreateJsonMapOutput(TString& str, const TProto2JsonConfig& config) { return MakeHolder<TJsonStringWriterOutput>(&str, config); - } + } - TJsonMapOutputPtr CreateJsonMapOutput(TStringStream& out, const TProto2JsonConfig& config) { + TJsonMapOutputPtr CreateJsonMapOutput(TStringStream& out, const TProto2JsonConfig& config) { return MakeHolder<TJsonWriterOutput>(&out, config); - } + } - TJsonMapOutputPtr CreateJsonMapOutput(IOutputStream& out, const TProto2JsonConfig& config) { + TJsonMapOutputPtr CreateJsonMapOutput(IOutputStream& out, const TProto2JsonConfig& config) { return MakeHolder<TJsonWriterOutput>(&out, config); - } + } - TJsonMapOutputPtr CreateJsonMapOutput(NJson::TJsonValue& json) { + TJsonMapOutputPtr CreateJsonMapOutput(NJson::TJsonValue& json) { return MakeHolder<TJsonValueOutput>(json); - } + } } diff --git a/library/cpp/protobuf/json/json_output_create.h b/library/cpp/protobuf/json/json_output_create.h index ad3889f5e9..ab63a89a11 100644 --- a/library/cpp/protobuf/json/json_output_create.h +++ b/library/cpp/protobuf/json/json_output_create.h @@ -4,19 +4,19 @@ #include "json_output.h" namespace NJson { - class TJsonValue; - class TJsonWriter; - struct TJsonWriterConfig; -} + class TJsonValue; + class TJsonWriter; + struct TJsonWriterConfig; +} class IOutputStream; class TStringStream; namespace NProtobufJson { - TJsonMapOutputPtr CreateJsonMapOutput(IOutputStream& out, const NJson::TJsonWriterConfig& config); - TJsonMapOutputPtr CreateJsonMapOutput(NJson::TJsonWriter& writer); - TJsonMapOutputPtr CreateJsonMapOutput(IOutputStream& out, const TProto2JsonConfig& config = TProto2JsonConfig()); - TJsonMapOutputPtr CreateJsonMapOutput(TString& str, const TProto2JsonConfig& config = TProto2JsonConfig()); - TJsonMapOutputPtr CreateJsonMapOutput(NJson::TJsonValue& json); + TJsonMapOutputPtr CreateJsonMapOutput(IOutputStream& out, const NJson::TJsonWriterConfig& config); + TJsonMapOutputPtr CreateJsonMapOutput(NJson::TJsonWriter& writer); + TJsonMapOutputPtr CreateJsonMapOutput(IOutputStream& out, const TProto2JsonConfig& config = TProto2JsonConfig()); + TJsonMapOutputPtr CreateJsonMapOutput(TString& str, const TProto2JsonConfig& config = TProto2JsonConfig()); + TJsonMapOutputPtr CreateJsonMapOutput(NJson::TJsonValue& json); -} +} diff --git a/library/cpp/protobuf/json/json_value_output.cpp b/library/cpp/protobuf/json/json_value_output.cpp index d845cc1c74..3ac95354d6 100644 --- a/library/cpp/protobuf/json/json_value_output.cpp +++ b/library/cpp/protobuf/json/json_value_output.cpp @@ -3,104 +3,104 @@ #include <library/cpp/json/json_reader.h> namespace NProtobufJson { - template <typename T> - void TJsonValueOutput::WriteImpl(const T& t) { - Y_ASSERT(Context.top().Type == TContext::JSON_ARRAY || Context.top().Type == TContext::JSON_AFTER_KEY); - - if (Context.top().Type == TContext::JSON_AFTER_KEY) { - Context.top().Value = t; - Context.pop(); - } else { - Context.top().Value.AppendValue(t); - } - } - - void TJsonValueOutput::DoWrite(const TStringBuf& s) { - WriteImpl(s); - } - - void TJsonValueOutput::DoWrite(const TString& s) { - WriteImpl(s); - } - - void TJsonValueOutput::DoWrite(int i) { - WriteImpl(i); - } - - void TJsonValueOutput::DoWrite(unsigned int i) { - WriteImpl(i); - } - - void TJsonValueOutput::DoWrite(long long i) { - WriteImpl(i); - } - - void TJsonValueOutput::DoWrite(unsigned long long i) { - WriteImpl(i); - } - - void TJsonValueOutput::DoWrite(float f) { - WriteImpl(f); - } - - void TJsonValueOutput::DoWrite(double f) { - WriteImpl(f); - } - - void TJsonValueOutput::DoWrite(bool b) { - WriteImpl(b); - } - - void TJsonValueOutput::DoWriteNull() { - WriteImpl(NJson::JSON_NULL); - } - - void TJsonValueOutput::DoBeginList() { - Y_ASSERT(Context.top().Type == TContext::JSON_ARRAY || Context.top().Type == TContext::JSON_AFTER_KEY); - - if (Context.top().Type == TContext::JSON_AFTER_KEY) { - Context.top().Type = TContext::JSON_ARRAY; - Context.top().Value.SetType(NJson::JSON_ARRAY); - } else { - Context.emplace(TContext::JSON_ARRAY, Context.top().Value.AppendValue(NJson::JSON_ARRAY)); - } - } - - void TJsonValueOutput::DoEndList() { - Y_ASSERT(Context.top().Type == TContext::JSON_ARRAY); - Context.pop(); - } - - void TJsonValueOutput::DoBeginObject() { - Y_ASSERT(Context.top().Type == TContext::JSON_ARRAY || Context.top().Type == TContext::JSON_AFTER_KEY); - - if (Context.top().Type == TContext::JSON_AFTER_KEY) { - Context.top().Type = TContext::JSON_MAP; - Context.top().Value.SetType(NJson::JSON_MAP); - } else { - Context.emplace(TContext::JSON_MAP, Context.top().Value.AppendValue(NJson::JSON_MAP)); - } - } - - void TJsonValueOutput::DoWriteKey(const TStringBuf& key) { - Y_ASSERT(Context.top().Type == TContext::JSON_MAP); - Context.emplace(TContext::JSON_AFTER_KEY, Context.top().Value[key]); - } - - void TJsonValueOutput::DoEndObject() { - Y_ASSERT(Context.top().Type == TContext::JSON_MAP); - Context.pop(); - } - - void TJsonValueOutput::DoWriteRawJson(const TStringBuf& str) { - Y_ASSERT(Context.top().Type == TContext::JSON_ARRAY || Context.top().Type == TContext::JSON_AFTER_KEY); - - if (Context.top().Type == TContext::JSON_AFTER_KEY) { - NJson::ReadJsonTree(str, &Context.top().Value); - Context.pop(); - } else { - NJson::ReadJsonTree(str, &Context.top().Value.AppendValue(NJson::JSON_UNDEFINED)); - } - } + template <typename T> + void TJsonValueOutput::WriteImpl(const T& t) { + Y_ASSERT(Context.top().Type == TContext::JSON_ARRAY || Context.top().Type == TContext::JSON_AFTER_KEY); + + if (Context.top().Type == TContext::JSON_AFTER_KEY) { + Context.top().Value = t; + Context.pop(); + } else { + Context.top().Value.AppendValue(t); + } + } + + void TJsonValueOutput::DoWrite(const TStringBuf& s) { + WriteImpl(s); + } + + void TJsonValueOutput::DoWrite(const TString& s) { + WriteImpl(s); + } + + void TJsonValueOutput::DoWrite(int i) { + WriteImpl(i); + } + + void TJsonValueOutput::DoWrite(unsigned int i) { + WriteImpl(i); + } + + void TJsonValueOutput::DoWrite(long long i) { + WriteImpl(i); + } + + void TJsonValueOutput::DoWrite(unsigned long long i) { + WriteImpl(i); + } + + void TJsonValueOutput::DoWrite(float f) { + WriteImpl(f); + } + + void TJsonValueOutput::DoWrite(double f) { + WriteImpl(f); + } + + void TJsonValueOutput::DoWrite(bool b) { + WriteImpl(b); + } + + void TJsonValueOutput::DoWriteNull() { + WriteImpl(NJson::JSON_NULL); + } + + void TJsonValueOutput::DoBeginList() { + Y_ASSERT(Context.top().Type == TContext::JSON_ARRAY || Context.top().Type == TContext::JSON_AFTER_KEY); + + if (Context.top().Type == TContext::JSON_AFTER_KEY) { + Context.top().Type = TContext::JSON_ARRAY; + Context.top().Value.SetType(NJson::JSON_ARRAY); + } else { + Context.emplace(TContext::JSON_ARRAY, Context.top().Value.AppendValue(NJson::JSON_ARRAY)); + } + } + + void TJsonValueOutput::DoEndList() { + Y_ASSERT(Context.top().Type == TContext::JSON_ARRAY); + Context.pop(); + } + + void TJsonValueOutput::DoBeginObject() { + Y_ASSERT(Context.top().Type == TContext::JSON_ARRAY || Context.top().Type == TContext::JSON_AFTER_KEY); + + if (Context.top().Type == TContext::JSON_AFTER_KEY) { + Context.top().Type = TContext::JSON_MAP; + Context.top().Value.SetType(NJson::JSON_MAP); + } else { + Context.emplace(TContext::JSON_MAP, Context.top().Value.AppendValue(NJson::JSON_MAP)); + } + } + + void TJsonValueOutput::DoWriteKey(const TStringBuf& key) { + Y_ASSERT(Context.top().Type == TContext::JSON_MAP); + Context.emplace(TContext::JSON_AFTER_KEY, Context.top().Value[key]); + } + + void TJsonValueOutput::DoEndObject() { + Y_ASSERT(Context.top().Type == TContext::JSON_MAP); + Context.pop(); + } + + void TJsonValueOutput::DoWriteRawJson(const TStringBuf& str) { + Y_ASSERT(Context.top().Type == TContext::JSON_ARRAY || Context.top().Type == TContext::JSON_AFTER_KEY); + + if (Context.top().Type == TContext::JSON_AFTER_KEY) { + NJson::ReadJsonTree(str, &Context.top().Value); + Context.pop(); + } else { + NJson::ReadJsonTree(str, &Context.top().Value.AppendValue(NJson::JSON_UNDEFINED)); + } + } } diff --git a/library/cpp/protobuf/json/json_value_output.h b/library/cpp/protobuf/json/json_value_output.h index 3fc6ff2ab0..8d2367eac7 100644 --- a/library/cpp/protobuf/json/json_value_output.h +++ b/library/cpp/protobuf/json/json_value_output.h @@ -7,57 +7,57 @@ #include <util/generic/stack.h> namespace NProtobufJson { - class TJsonValueOutput: public IJsonOutput { - public: - TJsonValueOutput(NJson::TJsonValue& value) - : Root(value) - { - Context.emplace(TContext::JSON_AFTER_KEY, Root); - } - - void DoWrite(const TStringBuf& s) override; - void DoWrite(const TString& s) override; - void DoWrite(int i) override; - void DoWrite(unsigned int i) override; - void DoWrite(long long i) override; - void DoWrite(unsigned long long i) override; - void DoWrite(float f) override; - void DoWrite(double f) override; - void DoWrite(bool b) override; - void DoWriteNull() override; - - void DoBeginList() override; - void DoEndList() override; - - void DoBeginObject() override; - void DoWriteKey(const TStringBuf& key) override; - void DoEndObject() override; - - void DoWriteRawJson(const TStringBuf& str) override; - - private: - template <typename T> - void WriteImpl(const T& t); - - struct TContext { - enum EType { - JSON_MAP, - JSON_ARRAY, - JSON_AFTER_KEY, - }; - - TContext(EType type, NJson::TJsonValue& value) - : Type(type) - , Value(value) - { - } - - EType Type; - NJson::TJsonValue& Value; + class TJsonValueOutput: public IJsonOutput { + public: + TJsonValueOutput(NJson::TJsonValue& value) + : Root(value) + { + Context.emplace(TContext::JSON_AFTER_KEY, Root); + } + + void DoWrite(const TStringBuf& s) override; + void DoWrite(const TString& s) override; + void DoWrite(int i) override; + void DoWrite(unsigned int i) override; + void DoWrite(long long i) override; + void DoWrite(unsigned long long i) override; + void DoWrite(float f) override; + void DoWrite(double f) override; + void DoWrite(bool b) override; + void DoWriteNull() override; + + void DoBeginList() override; + void DoEndList() override; + + void DoBeginObject() override; + void DoWriteKey(const TStringBuf& key) override; + void DoEndObject() override; + + void DoWriteRawJson(const TStringBuf& str) override; + + private: + template <typename T> + void WriteImpl(const T& t); + + struct TContext { + enum EType { + JSON_MAP, + JSON_ARRAY, + JSON_AFTER_KEY, + }; + + TContext(EType type, NJson::TJsonValue& value) + : Type(type) + , Value(value) + { + } + + EType Type; + NJson::TJsonValue& Value; }; - NJson::TJsonValue& Root; - TStack<TContext, TVector<TContext>> Context; + NJson::TJsonValue& Root; + TStack<TContext, TVector<TContext>> Context; }; -} +} diff --git a/library/cpp/protobuf/json/json_writer_output.cpp b/library/cpp/protobuf/json/json_writer_output.cpp index 288f645bab..b4ef84850c 100644 --- a/library/cpp/protobuf/json/json_writer_output.cpp +++ b/library/cpp/protobuf/json/json_writer_output.cpp @@ -1,22 +1,22 @@ #include "json_writer_output.h" namespace NProtobufJson { - NJson::TJsonWriterConfig TJsonWriterOutput::CreateJsonWriterConfig(const TProto2JsonConfig& config) { - NJson::TJsonWriterConfig jsonConfig; - jsonConfig.FormatOutput = config.FormatOutput; - jsonConfig.SortKeys = false; - jsonConfig.ValidateUtf8 = false; - jsonConfig.DontEscapeStrings = false; + NJson::TJsonWriterConfig TJsonWriterOutput::CreateJsonWriterConfig(const TProto2JsonConfig& config) { + NJson::TJsonWriterConfig jsonConfig; + jsonConfig.FormatOutput = config.FormatOutput; + jsonConfig.SortKeys = false; + jsonConfig.ValidateUtf8 = false; + jsonConfig.DontEscapeStrings = false; jsonConfig.WriteNanAsString = config.WriteNanAsString; - for (size_t i = 0; i < config.StringTransforms.size(); ++i) { - Y_ASSERT(config.StringTransforms[i]); - if (config.StringTransforms[i]->GetType() == IStringTransform::EscapeTransform) { - jsonConfig.DontEscapeStrings = true; - break; - } + for (size_t i = 0; i < config.StringTransforms.size(); ++i) { + Y_ASSERT(config.StringTransforms[i]); + if (config.StringTransforms[i]->GetType() == IStringTransform::EscapeTransform) { + jsonConfig.DontEscapeStrings = true; + break; + } } - return jsonConfig; + return jsonConfig; } - + } diff --git a/library/cpp/protobuf/json/json_writer_output.h b/library/cpp/protobuf/json/json_writer_output.h index 3d8a2daa56..bec4233018 100644 --- a/library/cpp/protobuf/json/json_writer_output.h +++ b/library/cpp/protobuf/json/json_writer_output.h @@ -9,95 +9,95 @@ #include <util/generic/store_policy.h> namespace NProtobufJson { - class TBaseJsonWriterOutput: public IJsonOutput { - public: - TBaseJsonWriterOutput(NJson::TJsonWriter& writer) - : Writer(writer) - { - } + class TBaseJsonWriterOutput: public IJsonOutput { + public: + TBaseJsonWriterOutput(NJson::TJsonWriter& writer) + : Writer(writer) + { + } - private: - void DoWrite(int i) override { - Writer.Write(i); - } - void DoWrite(unsigned int i) override { - Writer.Write(i); - } - void DoWrite(long long i) override { - Writer.Write(i); - } - void DoWrite(unsigned long long i) override { - Writer.Write(i); - } - void DoWrite(float f) override { - Writer.Write(f); - } - void DoWrite(double f) override { - Writer.Write(f); - } - void DoWrite(bool b) override { - Writer.Write(b); - } - void DoWriteNull() override { - Writer.WriteNull(); - } - void DoWrite(const TStringBuf& s) override { - Writer.Write(s); - } - void DoWrite(const TString& s) override { - Writer.Write(s); - } + private: + void DoWrite(int i) override { + Writer.Write(i); + } + void DoWrite(unsigned int i) override { + Writer.Write(i); + } + void DoWrite(long long i) override { + Writer.Write(i); + } + void DoWrite(unsigned long long i) override { + Writer.Write(i); + } + void DoWrite(float f) override { + Writer.Write(f); + } + void DoWrite(double f) override { + Writer.Write(f); + } + void DoWrite(bool b) override { + Writer.Write(b); + } + void DoWriteNull() override { + Writer.WriteNull(); + } + void DoWrite(const TStringBuf& s) override { + Writer.Write(s); + } + void DoWrite(const TString& s) override { + Writer.Write(s); + } - void DoBeginList() override { - Writer.OpenArray(); - } - void DoEndList() override { - Writer.CloseArray(); - } + void DoBeginList() override { + Writer.OpenArray(); + } + void DoEndList() override { + Writer.CloseArray(); + } - void DoBeginObject() override { - Writer.OpenMap(); - } - void DoWriteKey(const TStringBuf& key) override { - Writer.Write(key); - } - void DoEndObject() override { - Writer.CloseMap(); - } + void DoBeginObject() override { + Writer.OpenMap(); + } + void DoWriteKey(const TStringBuf& key) override { + Writer.Write(key); + } + void DoEndObject() override { + Writer.CloseMap(); + } - void DoWriteRawJson(const TStringBuf& str) override { - Writer.UnsafeWrite(str); - } + void DoWriteRawJson(const TStringBuf& str) override { + Writer.UnsafeWrite(str); + } - NJson::TJsonWriter& Writer; - }; + NJson::TJsonWriter& Writer; + }; - class TJsonWriterOutput: public TEmbedPolicy<NJson::TJsonWriter>, public TBaseJsonWriterOutput { - public: - TJsonWriterOutput(IOutputStream* outputStream, const NJson::TJsonWriterConfig& cfg) - : TEmbedPolicy<NJson::TJsonWriter>(outputStream, cfg) - , TBaseJsonWriterOutput(*Ptr()) - { - } + class TJsonWriterOutput: public TEmbedPolicy<NJson::TJsonWriter>, public TBaseJsonWriterOutput { + public: + TJsonWriterOutput(IOutputStream* outputStream, const NJson::TJsonWriterConfig& cfg) + : TEmbedPolicy<NJson::TJsonWriter>(outputStream, cfg) + , TBaseJsonWriterOutput(*Ptr()) + { + } - TJsonWriterOutput(IOutputStream* outputStream, const TProto2JsonConfig& cfg) - : TEmbedPolicy<NJson::TJsonWriter>(outputStream, CreateJsonWriterConfig(cfg)) - , TBaseJsonWriterOutput(*Ptr()) - { - } + TJsonWriterOutput(IOutputStream* outputStream, const TProto2JsonConfig& cfg) + : TEmbedPolicy<NJson::TJsonWriter>(outputStream, CreateJsonWriterConfig(cfg)) + , TBaseJsonWriterOutput(*Ptr()) + { + } - private: - static NJson::TJsonWriterConfig CreateJsonWriterConfig(const TProto2JsonConfig& cfg); - }; + private: + static NJson::TJsonWriterConfig CreateJsonWriterConfig(const TProto2JsonConfig& cfg); + }; - class TJsonStringWriterOutput: public TEmbedPolicy<TStringOutput>, public TJsonWriterOutput { - public: - template <typename TConfig> - TJsonStringWriterOutput(TString* str, const TConfig& cfg) - : TEmbedPolicy<TStringOutput>(*str) - , TJsonWriterOutput(TEmbedPolicy<TStringOutput>::Ptr(), cfg) - { - } - }; + class TJsonStringWriterOutput: public TEmbedPolicy<TStringOutput>, public TJsonWriterOutput { + public: + template <typename TConfig> + TJsonStringWriterOutput(TString* str, const TConfig& cfg) + : TEmbedPolicy<TStringOutput>(*str) + , TJsonWriterOutput(TEmbedPolicy<TStringOutput>::Ptr(), cfg) + { + } + }; -} +} diff --git a/library/cpp/protobuf/json/name_generator.h b/library/cpp/protobuf/json/name_generator.h index 2b5361bee2..d238283d03 100644 --- a/library/cpp/protobuf/json/name_generator.h +++ b/library/cpp/protobuf/json/name_generator.h @@ -5,14 +5,14 @@ #include <functional> namespace google { - namespace protobuf { - class FieldDescriptor; - class EnumValueDescriptor; - } -} + namespace protobuf { + class FieldDescriptor; + class EnumValueDescriptor; + } +} namespace NProtobufJson { - using TNameGenerator = std::function<TString(const google::protobuf::FieldDescriptor&)>; - using TEnumValueGenerator = std::function<TString(const google::protobuf::EnumValueDescriptor&)>; + using TNameGenerator = std::function<TString(const google::protobuf::FieldDescriptor&)>; + using TEnumValueGenerator = std::function<TString(const google::protobuf::EnumValueDescriptor&)>; -} +} diff --git a/library/cpp/protobuf/json/proto2json.cpp b/library/cpp/protobuf/json/proto2json.cpp index 3d76a91686..3083bd3422 100644 --- a/library/cpp/protobuf/json/proto2json.cpp +++ b/library/cpp/protobuf/json/proto2json.cpp @@ -14,43 +14,43 @@ #include <util/system/yassert.h> namespace NProtobufJson { - void Proto2Json(const NProtoBuf::Message& proto, IJsonOutput& jsonOutput, - const TProto2JsonConfig& config, bool closeMap) { - TProto2JsonPrinter printer(config); - printer.Print(proto, jsonOutput, closeMap); - } - - void Proto2Json(const NProtoBuf::Message& proto, NJson::TJsonValue& json, - const TProto2JsonConfig& config) { - Proto2Json(proto, *CreateJsonMapOutput(json), config); - } - - void Proto2Json(const NProtoBuf::Message& proto, NJson::TJsonWriter& writer, - const TProto2JsonConfig& config) { - Proto2Json(proto, *CreateJsonMapOutput(writer), config); - writer.Flush(); - } - - void Proto2Json(const NProtoBuf::Message& proto, IOutputStream& out, - const TProto2JsonConfig& config) { - Proto2Json(proto, *CreateJsonMapOutput(out, config), config); - } - - void Proto2Json(const NProtoBuf::Message& proto, TStringStream& out, - const TProto2JsonConfig& config) { - Proto2Json(proto, *CreateJsonMapOutput(out, config), config); - } - - void Proto2Json(const NProtoBuf::Message& proto, TString& str, - const TProto2JsonConfig& config) { - Proto2Json(proto, *CreateJsonMapOutput(str, config), config); - } - - TString Proto2Json(const ::NProtoBuf::Message& proto, - const TProto2JsonConfig& config) { - TString res; - Proto2Json(proto, res, config); - return res; - } + void Proto2Json(const NProtoBuf::Message& proto, IJsonOutput& jsonOutput, + const TProto2JsonConfig& config, bool closeMap) { + TProto2JsonPrinter printer(config); + printer.Print(proto, jsonOutput, closeMap); + } + + void Proto2Json(const NProtoBuf::Message& proto, NJson::TJsonValue& json, + const TProto2JsonConfig& config) { + Proto2Json(proto, *CreateJsonMapOutput(json), config); + } + + void Proto2Json(const NProtoBuf::Message& proto, NJson::TJsonWriter& writer, + const TProto2JsonConfig& config) { + Proto2Json(proto, *CreateJsonMapOutput(writer), config); + writer.Flush(); + } + + void Proto2Json(const NProtoBuf::Message& proto, IOutputStream& out, + const TProto2JsonConfig& config) { + Proto2Json(proto, *CreateJsonMapOutput(out, config), config); + } + + void Proto2Json(const NProtoBuf::Message& proto, TStringStream& out, + const TProto2JsonConfig& config) { + Proto2Json(proto, *CreateJsonMapOutput(out, config), config); + } + + void Proto2Json(const NProtoBuf::Message& proto, TString& str, + const TProto2JsonConfig& config) { + Proto2Json(proto, *CreateJsonMapOutput(str, config), config); + } + + TString Proto2Json(const ::NProtoBuf::Message& proto, + const TProto2JsonConfig& config) { + TString res; + Proto2Json(proto, res, config); + return res; + } } diff --git a/library/cpp/protobuf/json/proto2json.h b/library/cpp/protobuf/json/proto2json.h index 89a1781a40..55ee4e0846 100644 --- a/library/cpp/protobuf/json/proto2json.h +++ b/library/cpp/protobuf/json/proto2json.h @@ -15,64 +15,64 @@ #include <functional> namespace NJson { - class TJsonValue; - class TJsonWriter; -} + class TJsonValue; + class TJsonWriter; +} class IOutputStream; class TStringStream; namespace NProtobufJson { - void Proto2Json(const NProtoBuf::Message& proto, IJsonOutput& jsonOutput, - const TProto2JsonConfig& config = TProto2JsonConfig(), bool closeMap = true); + void Proto2Json(const NProtoBuf::Message& proto, IJsonOutput& jsonOutput, + const TProto2JsonConfig& config = TProto2JsonConfig(), bool closeMap = true); - void Proto2Json(const NProtoBuf::Message& proto, NJson::TJsonWriter& writer, - const TProto2JsonConfig& config = TProto2JsonConfig()); + void Proto2Json(const NProtoBuf::Message& proto, NJson::TJsonWriter& writer, + const TProto2JsonConfig& config = TProto2JsonConfig()); - /// @throw yexception - void Proto2Json(const NProtoBuf::Message& proto, NJson::TJsonValue& json, - const TProto2JsonConfig& config = TProto2JsonConfig()); + /// @throw yexception + void Proto2Json(const NProtoBuf::Message& proto, NJson::TJsonValue& json, + const TProto2JsonConfig& config = TProto2JsonConfig()); - /// @throw yexception - void Proto2Json(const NProtoBuf::Message& proto, IOutputStream& out, - const TProto2JsonConfig& config); - // Generated code shortcut - template <class T> - inline void Proto2Json(const T& proto, IOutputStream& out) { - out << proto.AsJSON(); - } + /// @throw yexception + void Proto2Json(const NProtoBuf::Message& proto, IOutputStream& out, + const TProto2JsonConfig& config); + // Generated code shortcut + template <class T> + inline void Proto2Json(const T& proto, IOutputStream& out) { + out << proto.AsJSON(); + } - // TStringStream deserves a special overload as its operator TString() would cause ambiguity - /// @throw yexception - void Proto2Json(const NProtoBuf::Message& proto, TStringStream& out, - const TProto2JsonConfig& config); - // Generated code shortcut - template <class T> - inline void Proto2Json(const T& proto, TStringStream& out) { - out << proto.AsJSON(); - } + // TStringStream deserves a special overload as its operator TString() would cause ambiguity + /// @throw yexception + void Proto2Json(const NProtoBuf::Message& proto, TStringStream& out, + const TProto2JsonConfig& config); + // Generated code shortcut + template <class T> + inline void Proto2Json(const T& proto, TStringStream& out) { + out << proto.AsJSON(); + } - /// @throw yexception - void Proto2Json(const NProtoBuf::Message& proto, TString& str, - const TProto2JsonConfig& config); - // Generated code shortcut - template <class T> - inline void Proto2Json(const T& proto, TString& str) { - str.clear(); - TStringOutput out(str); - out << proto.AsJSON(); - } + /// @throw yexception + void Proto2Json(const NProtoBuf::Message& proto, TString& str, + const TProto2JsonConfig& config); + // Generated code shortcut + template <class T> + inline void Proto2Json(const T& proto, TString& str) { + str.clear(); + TStringOutput out(str); + out << proto.AsJSON(); + } - /// @throw yexception - TString Proto2Json(const NProtoBuf::Message& proto, - const TProto2JsonConfig& config); + /// @throw yexception + TString Proto2Json(const NProtoBuf::Message& proto, + const TProto2JsonConfig& config); // Returns incorrect result if proto contains another NProtoBuf::Message - // Generated code shortcut - template <class T> - inline TString Proto2Json(const T& proto) { - TString result; - Proto2Json(proto, result); - return result; - } + // Generated code shortcut + template <class T> + inline TString Proto2Json(const T& proto) { + TString result; + Proto2Json(proto, result); + return result; + } } diff --git a/library/cpp/protobuf/json/proto2json_printer.cpp b/library/cpp/protobuf/json/proto2json_printer.cpp index 6123eab0f2..c2e2f1814f 100644 --- a/library/cpp/protobuf/json/proto2json_printer.cpp +++ b/library/cpp/protobuf/json/proto2json_printer.cpp @@ -192,15 +192,15 @@ namespace NProtobufJson { break; \ } -#define INT_FIELD_TO_JSON(EProtoCppType, ProtoGet) \ - case FieldDescriptor::EProtoCppType: { \ - const auto value = reflection->ProtoGet(proto, &field); \ - if (NeedStringifyNumber(value)) { \ - json.WriteKey(key).Write(ToString(value)); \ - } else { \ - json.WriteKey(key).Write(value); \ - } \ - break; \ +#define INT_FIELD_TO_JSON(EProtoCppType, ProtoGet) \ + case FieldDescriptor::EProtoCppType: { \ + const auto value = reflection->ProtoGet(proto, &field); \ + if (NeedStringifyNumber(value)) { \ + json.WriteKey(key).Write(ToString(value)); \ + } else { \ + json.WriteKey(key).Write(value); \ + } \ + break; \ } const Reflection* reflection = proto.GetReflection(); diff --git a/library/cpp/protobuf/json/string_transform.cpp b/library/cpp/protobuf/json/string_transform.cpp index 7c42daa677..6f982ece61 100644 --- a/library/cpp/protobuf/json/string_transform.cpp +++ b/library/cpp/protobuf/json/string_transform.cpp @@ -5,53 +5,53 @@ #include <library/cpp/string_utils/base64/base64.h> namespace NProtobufJson { - void TCEscapeTransform::Transform(TString& str) const { - str = google::protobuf::CEscape(str); - } + void TCEscapeTransform::Transform(TString& str) const { + str = google::protobuf::CEscape(str); + } - void TSafeUtf8CEscapeTransform::Transform(TString& str) const { - str = google::protobuf::strings::Utf8SafeCEscape(str); - } + void TSafeUtf8CEscapeTransform::Transform(TString& str) const { + str = google::protobuf::strings::Utf8SafeCEscape(str); + } - void TDoubleEscapeTransform::Transform(TString& str) const { - TString escaped = google::protobuf::CEscape(str); - str = ""; - for (char* it = escaped.begin(); *it; ++it) { - if (*it == '\\' || *it == '\"') - str += "\\"; - str += *it; - } - } + void TDoubleEscapeTransform::Transform(TString& str) const { + TString escaped = google::protobuf::CEscape(str); + str = ""; + for (char* it = escaped.begin(); *it; ++it) { + if (*it == '\\' || *it == '\"') + str += "\\"; + str += *it; + } + } - void TDoubleUnescapeTransform::Transform(TString& str) const { - str = google::protobuf::UnescapeCEscapeString(Unescape(str)); + void TDoubleUnescapeTransform::Transform(TString& str) const { + str = google::protobuf::UnescapeCEscapeString(Unescape(str)); } - TString TDoubleUnescapeTransform::Unescape(const TString& str) const { - if (str.empty()) { - return str; - } + TString TDoubleUnescapeTransform::Unescape(const TString& str) const { + if (str.empty()) { + return str; + } - TString result; - result.reserve(str.size()); + TString result; + result.reserve(str.size()); - char prev = str[0]; - bool doneOutput = true; - for (const char* it = str.c_str() + 1; *it; ++it) { - if (doneOutput && prev == '\\' && (*it == '\\' || *it == '\"')) { - doneOutput = false; - } else { - result += prev; - doneOutput = true; - } - prev = *it; - } + char prev = str[0]; + bool doneOutput = true; + for (const char* it = str.c_str() + 1; *it; ++it) { + if (doneOutput && prev == '\\' && (*it == '\\' || *it == '\"')) { + doneOutput = false; + } else { + result += prev; + doneOutput = true; + } + prev = *it; + } - if ((doneOutput && prev != '\\') || !doneOutput) { + if ((doneOutput && prev != '\\') || !doneOutput) { result += prev; } - return result; + return result; } void TBase64EncodeBytesTransform::TransformBytes(TString &str) const { diff --git a/library/cpp/protobuf/json/string_transform.h b/library/cpp/protobuf/json/string_transform.h index e4b296bc01..76042ddc23 100644 --- a/library/cpp/protobuf/json/string_transform.h +++ b/library/cpp/protobuf/json/string_transform.h @@ -5,83 +5,83 @@ #include <util/generic/refcount.h> namespace NProtobufJson { - class IStringTransform: public TSimpleRefCount<IStringTransform> { - public: - virtual ~IStringTransform() { - } - - /// Some transforms have special meaning. - /// For example, escape transforms cause generic JSON escaping to be turned off. - enum Type { - EscapeTransform = 0x1, - }; - - virtual int GetType() const = 0; - - /// This method is called for each string field in proto - virtual void Transform(TString& str) const = 0; - - /// This method is called for each bytes field in proto - virtual void TransformBytes(TString& str) const { - // Default behaviour is to apply string transform - return Transform(str); - } - }; - - using TStringTransformPtr = TIntrusivePtr<IStringTransform>; - - template <bool quote, bool tounicode> - class TEscapeJTransform: public IStringTransform { - public: - int GetType() const override { - return EscapeTransform; - } - - void Transform(TString& str) const override { - TString newStr; - NEscJ::EscapeJ<quote, tounicode>(str, newStr); - str = newStr; - } - }; - - class TCEscapeTransform: public IStringTransform { - public: - int GetType() const override { - return EscapeTransform; - } - - void Transform(TString& str) const override; - }; - - class TSafeUtf8CEscapeTransform: public IStringTransform { - public: - int GetType() const override { - return EscapeTransform; - } - - void Transform(TString& str) const override; - }; - - class TDoubleEscapeTransform: public IStringTransform { - public: - int GetType() const override { - return EscapeTransform; - } - - void Transform(TString& str) const override; - }; - - class TDoubleUnescapeTransform: public NProtobufJson::IStringTransform { - public: - int GetType() const override { - return NProtobufJson::IStringTransform::EscapeTransform; - } - - void Transform(TString& str) const override; - - private: - TString Unescape(const TString& str) const; - }; + class IStringTransform: public TSimpleRefCount<IStringTransform> { + public: + virtual ~IStringTransform() { + } + + /// Some transforms have special meaning. + /// For example, escape transforms cause generic JSON escaping to be turned off. + enum Type { + EscapeTransform = 0x1, + }; + + virtual int GetType() const = 0; + + /// This method is called for each string field in proto + virtual void Transform(TString& str) const = 0; + + /// This method is called for each bytes field in proto + virtual void TransformBytes(TString& str) const { + // Default behaviour is to apply string transform + return Transform(str); + } + }; + + using TStringTransformPtr = TIntrusivePtr<IStringTransform>; + + template <bool quote, bool tounicode> + class TEscapeJTransform: public IStringTransform { + public: + int GetType() const override { + return EscapeTransform; + } + + void Transform(TString& str) const override { + TString newStr; + NEscJ::EscapeJ<quote, tounicode>(str, newStr); + str = newStr; + } + }; + + class TCEscapeTransform: public IStringTransform { + public: + int GetType() const override { + return EscapeTransform; + } + + void Transform(TString& str) const override; + }; + + class TSafeUtf8CEscapeTransform: public IStringTransform { + public: + int GetType() const override { + return EscapeTransform; + } + + void Transform(TString& str) const override; + }; + + class TDoubleEscapeTransform: public IStringTransform { + public: + int GetType() const override { + return EscapeTransform; + } + + void Transform(TString& str) const override; + }; + + class TDoubleUnescapeTransform: public NProtobufJson::IStringTransform { + public: + int GetType() const override { + return NProtobufJson::IStringTransform::EscapeTransform; + } + + void Transform(TString& str) const override; + + private: + TString Unescape(const TString& str) const; + }; class TBase64EncodeBytesTransform: public NProtobufJson::IStringTransform { public: @@ -108,4 +108,4 @@ namespace NProtobufJson { void TransformBytes(TString &str) const override; }; -} +} diff --git a/library/cpp/protobuf/json/ut/filter_ut.cpp b/library/cpp/protobuf/json/ut/filter_ut.cpp index 95c227666f..0e2c13649a 100644 --- a/library/cpp/protobuf/json/ut/filter_ut.cpp +++ b/library/cpp/protobuf/json/ut/filter_ut.cpp @@ -22,72 +22,72 @@ static NProtobufJsonUt::TFilterTest GetTestMsg() { Y_UNIT_TEST_SUITE(TProto2JsonFilterTest){ Y_UNIT_TEST(TestFilterPrinter){ NProtobufJsonUt::TFilterTest msg = GetTestMsg(); -{ - TString expected = R"({"OptFiltered":"1","NotFiltered":"23","RepFiltered":[45,67],)" - R"("Inner":{"Number":[100,200],"InnerFiltered":235}})"; - TString my = Proto2Json(msg); - UNIT_ASSERT_STRINGS_EQUAL(my, expected); -} - -{ - TString expected = R"({"NotFiltered":"23",)" - R"("Inner":{"Number":[100,200]}})"; - TString my = PrintWithFilter(msg, MakeFieldOptionFunctor(NProtobufJsonUt::filter_test, false)); - UNIT_ASSERT_STRINGS_EQUAL(my, expected); -} +{ + TString expected = R"({"OptFiltered":"1","NotFiltered":"23","RepFiltered":[45,67],)" + R"("Inner":{"Number":[100,200],"InnerFiltered":235}})"; + TString my = Proto2Json(msg); + UNIT_ASSERT_STRINGS_EQUAL(my, expected); +} -{ - TString expected = R"({"OptFiltered":"1","RepFiltered":[45,67]})"; - TString my = PrintWithFilter(msg, MakeFieldOptionFunctor(NProtobufJsonUt::filter_test)); - UNIT_ASSERT_STRINGS_EQUAL(my, expected); -} +{ + TString expected = R"({"NotFiltered":"23",)" + R"("Inner":{"Number":[100,200]}})"; + TString my = PrintWithFilter(msg, MakeFieldOptionFunctor(NProtobufJsonUt::filter_test, false)); + UNIT_ASSERT_STRINGS_EQUAL(my, expected); +} -{ - TString expected = R"({"OptFiltered":"1","NotFiltered":"23",)" - R"("Inner":{"Number":[100,200]}})"; - TString my; - PrintWithFilter(msg, MakeFieldOptionFunctor(NProtobufJsonUt::export_test), *CreateJsonMapOutput(my)); - UNIT_ASSERT_STRINGS_EQUAL(my, expected); -} - -{ - TString expected = R"({"NotFiltered":"23",)" - R"("Inner":{"Number":[100,200]}})"; - auto functor = [](const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor* field) { - return field->name() == "NotFiltered" || field->name() == "Number" || field->name() == "Inner"; - }; - TString my = PrintWithFilter(msg, functor); - UNIT_ASSERT_STRINGS_EQUAL(my, expected); -} -} +{ + TString expected = R"({"OptFiltered":"1","RepFiltered":[45,67]})"; + TString my = PrintWithFilter(msg, MakeFieldOptionFunctor(NProtobufJsonUt::filter_test)); + UNIT_ASSERT_STRINGS_EQUAL(my, expected); +} +{ + TString expected = R"({"OptFiltered":"1","NotFiltered":"23",)" + R"("Inner":{"Number":[100,200]}})"; + TString my; + PrintWithFilter(msg, MakeFieldOptionFunctor(NProtobufJsonUt::export_test), *CreateJsonMapOutput(my)); + UNIT_ASSERT_STRINGS_EQUAL(my, expected); +} + +{ + TString expected = R"({"NotFiltered":"23",)" + R"("Inner":{"Number":[100,200]}})"; + auto functor = [](const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor* field) { + return field->name() == "NotFiltered" || field->name() == "Number" || field->name() == "Inner"; + }; + TString my = PrintWithFilter(msg, functor); + UNIT_ASSERT_STRINGS_EQUAL(my, expected); +} +} + Y_UNIT_TEST(NoUnnecessaryCopyFunctor) { - size_t CopyCount = 0; - struct TFunctorMock { - TFunctorMock(size_t* copyCount) - : CopyCount(copyCount) + size_t CopyCount = 0; + struct TFunctorMock { + TFunctorMock(size_t* copyCount) + : CopyCount(copyCount) { - UNIT_ASSERT(*CopyCount <= 1); + UNIT_ASSERT(*CopyCount <= 1); } - TFunctorMock(const TFunctorMock& f) - : CopyCount(f.CopyCount) + TFunctorMock(const TFunctorMock& f) + : CopyCount(f.CopyCount) { - ++*CopyCount; + ++*CopyCount; } - TFunctorMock(TFunctorMock&& f) = default; + TFunctorMock(TFunctorMock&& f) = default; - bool operator()(const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor*) const { - return false; - } + bool operator()(const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor*) const { + return false; + } - size_t* CopyCount; - }; + size_t* CopyCount; + }; - TProto2JsonConfig cfg; - TFilteringPrinter<> printer(TFunctorMock(&CopyCount), cfg); - UNIT_ASSERT(CopyCount <= 1); -} -} -; + TProto2JsonConfig cfg; + TFilteringPrinter<> printer(TFunctorMock(&CopyCount), cfg); + UNIT_ASSERT(CopyCount <= 1); +} +} +; diff --git a/library/cpp/protobuf/json/ut/inline_ut.cpp b/library/cpp/protobuf/json/ut/inline_ut.cpp index c29ad32e7d..0960de3220 100644 --- a/library/cpp/protobuf/json/ut/inline_ut.cpp +++ b/library/cpp/protobuf/json/ut/inline_ut.cpp @@ -24,99 +24,99 @@ static NProtobufJsonUt::TInlineTest GetTestMsg() { Y_UNIT_TEST_SUITE(TProto2JsonInlineTest){ Y_UNIT_TEST(TestNormalPrint){ NProtobufJsonUt::TInlineTest msg = GetTestMsg(); -// normal print should output these fields as just string values -TString expRaw = R"({"OptJson":"{\"a\":1,\"b\":\"000\"}","NotJson":"12{}34","RepJson":["{}","[1,2]"],)" - R"("Inner":{"Number":[100,200],"InnerJson":"{\"xxx\":[]}"}})"; -TString myRaw; -Proto2Json(msg, myRaw); -UNIT_ASSERT_STRINGS_EQUAL(myRaw, expRaw); - -myRaw = PrintInlined(msg, [](const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor*) { return false; }); -UNIT_ASSERT_STRINGS_EQUAL(myRaw, expRaw); // result is the same -} +// normal print should output these fields as just string values +TString expRaw = R"({"OptJson":"{\"a\":1,\"b\":\"000\"}","NotJson":"12{}34","RepJson":["{}","[1,2]"],)" + R"("Inner":{"Number":[100,200],"InnerJson":"{\"xxx\":[]}"}})"; +TString myRaw; +Proto2Json(msg, myRaw); +UNIT_ASSERT_STRINGS_EQUAL(myRaw, expRaw); + +myRaw = PrintInlined(msg, [](const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor*) { return false; }); +UNIT_ASSERT_STRINGS_EQUAL(myRaw, expRaw); // result is the same +} Y_UNIT_TEST(TestInliningPrinter) { - NProtobufJsonUt::TInlineTest msg = GetTestMsg(); - // inlined print should output these fields as inlined json sub-objects - TString expInlined = R"({"OptJson":{"a":1,"b":"000"},"NotJson":"12{}34","RepJson":[{},[1,2]],)" - R"("Inner":{"Number":[100,200],"InnerJson":{"xxx":[]}}})"; - - { - TString myInlined = PrintInlined(msg, MakeFieldOptionFunctor(NProtobufJsonUt::inline_test)); - UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined); + NProtobufJsonUt::TInlineTest msg = GetTestMsg(); + // inlined print should output these fields as inlined json sub-objects + TString expInlined = R"({"OptJson":{"a":1,"b":"000"},"NotJson":"12{}34","RepJson":[{},[1,2]],)" + R"("Inner":{"Number":[100,200],"InnerJson":{"xxx":[]}}})"; + + { + TString myInlined = PrintInlined(msg, MakeFieldOptionFunctor(NProtobufJsonUt::inline_test)); + UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined); } - { - auto functor = [](const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor* field) { - return field->name() == "OptJson" || field->name() == "RepJson" || field->name() == "InnerJson"; - }; - TString myInlined = PrintInlined(msg, functor); - UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined); - } -} + { + auto functor = [](const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor* field) { + return field->name() == "OptJson" || field->name() == "RepJson" || field->name() == "InnerJson"; + }; + TString myInlined = PrintInlined(msg, functor); + UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined); + } +} Y_UNIT_TEST(TestNoValues) { - // no values - no printing - NProtobufJsonUt::TInlineTest msg; - msg.MutableInner()->AddNumber(100); - msg.MutableInner()->AddNumber(200); + // no values - no printing + NProtobufJsonUt::TInlineTest msg; + msg.MutableInner()->AddNumber(100); + msg.MutableInner()->AddNumber(200); - TString expInlined = R"({"Inner":{"Number":[100,200]}})"; + TString expInlined = R"({"Inner":{"Number":[100,200]}})"; - TString myInlined = PrintInlined(msg, MakeFieldOptionFunctor(NProtobufJsonUt::inline_test)); - UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined); -} + TString myInlined = PrintInlined(msg, MakeFieldOptionFunctor(NProtobufJsonUt::inline_test)); + UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined); +} Y_UNIT_TEST(TestMissingKeyModeNull) { - NProtobufJsonUt::TInlineTest msg; - msg.MutableInner()->AddNumber(100); - msg.MutableInner()->AddNumber(200); + NProtobufJsonUt::TInlineTest msg; + msg.MutableInner()->AddNumber(100); + msg.MutableInner()->AddNumber(200); - TString expInlined = R"({"OptJson":null,"NotJson":null,"RepJson":null,"Inner":{"Number":[100,200],"InnerJson":null}})"; + TString expInlined = R"({"OptJson":null,"NotJson":null,"RepJson":null,"Inner":{"Number":[100,200],"InnerJson":null}})"; - TProto2JsonConfig cfg; - cfg.SetMissingSingleKeyMode(TProto2JsonConfig::MissingKeyNull).SetMissingRepeatedKeyMode(TProto2JsonConfig::MissingKeyNull); - TString myInlined = PrintInlined(msg, MakeFieldOptionFunctor(NProtobufJsonUt::inline_test), cfg); - UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined); -} + TProto2JsonConfig cfg; + cfg.SetMissingSingleKeyMode(TProto2JsonConfig::MissingKeyNull).SetMissingRepeatedKeyMode(TProto2JsonConfig::MissingKeyNull); + TString myInlined = PrintInlined(msg, MakeFieldOptionFunctor(NProtobufJsonUt::inline_test), cfg); + UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined); +} Y_UNIT_TEST(TestMissingKeyModeDefault) { - NProtobufJsonUt::TInlineTestDefaultValues msg; + NProtobufJsonUt::TInlineTestDefaultValues msg; - TString expInlined = R"({"OptJson":{"default":1},"Number":0,"RepJson":[],"Inner":{"OptJson":{"default":2}}})"; + TString expInlined = R"({"OptJson":{"default":1},"Number":0,"RepJson":[],"Inner":{"OptJson":{"default":2}}})"; - TProto2JsonConfig cfg; - cfg.SetMissingSingleKeyMode(TProto2JsonConfig::MissingKeyDefault).SetMissingRepeatedKeyMode(TProto2JsonConfig::MissingKeyDefault); - TString myInlined = PrintInlined(msg, MakeFieldOptionFunctor(NProtobufJsonUt::inline_test), cfg); - UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined); -} + TProto2JsonConfig cfg; + cfg.SetMissingSingleKeyMode(TProto2JsonConfig::MissingKeyDefault).SetMissingRepeatedKeyMode(TProto2JsonConfig::MissingKeyDefault); + TString myInlined = PrintInlined(msg, MakeFieldOptionFunctor(NProtobufJsonUt::inline_test), cfg); + UNIT_ASSERT_STRINGS_EQUAL(myInlined, expInlined); +} Y_UNIT_TEST(NoUnnecessaryCopyFunctor) { - size_t CopyCount = 0; - struct TFunctorMock { - TFunctorMock(size_t* copyCount) - : CopyCount(copyCount) - { - UNIT_ASSERT(*CopyCount <= 1); - } - - TFunctorMock(const TFunctorMock& f) - : CopyCount(f.CopyCount) - { - ++*CopyCount; - } - - TFunctorMock(TFunctorMock&& f) = default; - - bool operator()(const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor*) const { - return false; - } - - size_t* CopyCount; - }; - - TProto2JsonConfig cfg; - TInliningPrinter<> printer(TFunctorMock(&CopyCount), cfg); - UNIT_ASSERT(CopyCount <= 1); -} -} -; + size_t CopyCount = 0; + struct TFunctorMock { + TFunctorMock(size_t* copyCount) + : CopyCount(copyCount) + { + UNIT_ASSERT(*CopyCount <= 1); + } + + TFunctorMock(const TFunctorMock& f) + : CopyCount(f.CopyCount) + { + ++*CopyCount; + } + + TFunctorMock(TFunctorMock&& f) = default; + + bool operator()(const NProtoBuf::Message&, const NProtoBuf::FieldDescriptor*) const { + return false; + } + + size_t* CopyCount; + }; + + TProto2JsonConfig cfg; + TInliningPrinter<> printer(TFunctorMock(&CopyCount), cfg); + UNIT_ASSERT(CopyCount <= 1); +} +} +; diff --git a/library/cpp/protobuf/json/ut/json.h b/library/cpp/protobuf/json/ut/json.h index c1f108e6e4..bdab69f4d4 100644 --- a/library/cpp/protobuf/json/ut/json.h +++ b/library/cpp/protobuf/json/ut/json.h @@ -12,58 +12,58 @@ #include <util/system/defaults.h> namespace NProtobufJsonTest { - inline NJson::TJsonValue - CreateFlatJson(const THashSet<TString>& skippedKeys = THashSet<TString>()) { - NJson::TJsonValue json; + inline NJson::TJsonValue + CreateFlatJson(const THashSet<TString>& skippedKeys = THashSet<TString>()) { + NJson::TJsonValue json; -#define DEFINE_FIELD(name, value) \ - if (skippedKeys.find(#name) == skippedKeys.end()) \ +#define DEFINE_FIELD(name, value) \ + if (skippedKeys.find(#name) == skippedKeys.end()) \ json.InsertValue(#name, value); #include "fields.incl" #undef DEFINE_FIELD - return json; - } - - inline NJson::TJsonValue - CreateRepeatedFlatJson(const THashSet<TString>& skippedKeys = THashSet<TString>()) { - NJson::TJsonValue json; - -#define DEFINE_REPEATED_FIELD(name, type, ...) \ - if (skippedKeys.find(#name) == skippedKeys.end()) { \ - type values[] = {__VA_ARGS__}; \ - NJson::TJsonValue array(NJson::JSON_ARRAY); \ - for (size_t i = 0, end = Y_ARRAY_SIZE(values); i < end; ++i) { \ - array.AppendValue(values[i]); \ - } \ - json.InsertValue(#name, array); \ + return json; + } + + inline NJson::TJsonValue + CreateRepeatedFlatJson(const THashSet<TString>& skippedKeys = THashSet<TString>()) { + NJson::TJsonValue json; + +#define DEFINE_REPEATED_FIELD(name, type, ...) \ + if (skippedKeys.find(#name) == skippedKeys.end()) { \ + type values[] = {__VA_ARGS__}; \ + NJson::TJsonValue array(NJson::JSON_ARRAY); \ + for (size_t i = 0, end = Y_ARRAY_SIZE(values); i < end; ++i) { \ + array.AppendValue(values[i]); \ + } \ + json.InsertValue(#name, array); \ } #include "repeated_fields.incl" #undef DEFINE_REPEATED_FIELD - return json; - } + return json; + } - inline NJson::TJsonValue - CreateCompositeJson(const THashSet<TString>& skippedKeys = THashSet<TString>()) { - const NJson::TJsonValue& part = CreateFlatJson(skippedKeys); - NJson::TJsonValue json; - json.InsertValue("Part", part); + inline NJson::TJsonValue + CreateCompositeJson(const THashSet<TString>& skippedKeys = THashSet<TString>()) { + const NJson::TJsonValue& part = CreateFlatJson(skippedKeys); + NJson::TJsonValue json; + json.InsertValue("Part", part); - return json; - } + return json; + } -#define UNIT_ASSERT_JSONS_EQUAL(lhs, rhs) \ - if (lhs != rhs) { \ +#define UNIT_ASSERT_JSONS_EQUAL(lhs, rhs) \ + if (lhs != rhs) { \ UNIT_ASSERT_STRINGS_EQUAL(lhs.GetStringRobust(), rhs.GetStringRobust()); \ } -#define UNIT_ASSERT_JSON_STRINGS_EQUAL(lhs, rhs) \ - if (lhs != rhs) { \ - NJson::TJsonValue _lhs_json, _rhs_json; \ +#define UNIT_ASSERT_JSON_STRINGS_EQUAL(lhs, rhs) \ + if (lhs != rhs) { \ + NJson::TJsonValue _lhs_json, _rhs_json; \ UNIT_ASSERT(NJson::ReadJsonTree(lhs, &_lhs_json)); \ UNIT_ASSERT(NJson::ReadJsonTree(rhs, &_rhs_json)); \ - UNIT_ASSERT_JSONS_EQUAL(_lhs_json, _rhs_json); \ + UNIT_ASSERT_JSONS_EQUAL(_lhs_json, _rhs_json); \ } -} +} diff --git a/library/cpp/protobuf/json/ut/json2proto_ut.cpp b/library/cpp/protobuf/json/ut/json2proto_ut.cpp index 0dfe57bc7a..c8fbcce65c 100644 --- a/library/cpp/protobuf/json/ut/json2proto_ut.cpp +++ b/library/cpp/protobuf/json/ut/json2proto_ut.cpp @@ -24,13 +24,13 @@ using namespace NProtobufJson; using namespace NProtobufJsonTest; namespace google { - namespace protobuf { - namespace internal { - void MapTestForceDeterministic() { - google::protobuf::io::CodedOutputStream::SetDefaultSerializationDeterministic(); - } - } - } // namespace protobuf + namespace protobuf { + namespace internal { + void MapTestForceDeterministic() { + google::protobuf::io::CodedOutputStream::SetDefaultSerializationDeterministic(); + } + } + } // namespace protobuf } namespace { @@ -72,331 +72,331 @@ namespace { Y_UNIT_TEST_SUITE(TJson2ProtoTest) { Y_UNIT_TEST(TestFlatOptional){ - {const NJson::TJsonValue& json = CreateFlatJson(); - TFlatOptional proto; - Json2Proto(json, proto); - TFlatOptional modelProto; - FillFlatProto(&modelProto); - UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); -} - - // Try to skip each field -#define DEFINE_FIELD(name, value) \ - { \ - THashSet<TString> skippedField; \ - skippedField.insert(#name); \ - const NJson::TJsonValue& json = CreateFlatJson(skippedField); \ - TFlatOptional proto; \ - Json2Proto(json, proto); \ - TFlatOptional modelProto; \ - FillFlatProto(&modelProto, skippedField); \ - UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); \ - } + {const NJson::TJsonValue& json = CreateFlatJson(); + TFlatOptional proto; + Json2Proto(json, proto); + TFlatOptional modelProto; + FillFlatProto(&modelProto); + UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); +} + + // Try to skip each field +#define DEFINE_FIELD(name, value) \ + { \ + THashSet<TString> skippedField; \ + skippedField.insert(#name); \ + const NJson::TJsonValue& json = CreateFlatJson(skippedField); \ + TFlatOptional proto; \ + Json2Proto(json, proto); \ + TFlatOptional modelProto; \ + FillFlatProto(&modelProto, skippedField); \ + UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); \ + } #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD -} // TestFlatOptional +} // TestFlatOptional Y_UNIT_TEST(TestFlatRequired){ - {const NJson::TJsonValue& json = CreateFlatJson(); -TFlatRequired proto; -Json2Proto(json, proto); -TFlatRequired modelProto; -FillFlatProto(&modelProto); -UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); -} - -// Try to skip each field -#define DEFINE_FIELD(name, value) \ - { \ - THashSet<TString> skippedField; \ - skippedField.insert(#name); \ - const NJson::TJsonValue& json = CreateFlatJson(skippedField); \ - TFlatRequired proto; \ - UNIT_ASSERT_EXCEPTION(Json2Proto(json, proto), yexception); \ - } + {const NJson::TJsonValue& json = CreateFlatJson(); +TFlatRequired proto; +Json2Proto(json, proto); +TFlatRequired modelProto; +FillFlatProto(&modelProto); +UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); +} + +// Try to skip each field +#define DEFINE_FIELD(name, value) \ + { \ + THashSet<TString> skippedField; \ + skippedField.insert(#name); \ + const NJson::TJsonValue& json = CreateFlatJson(skippedField); \ + TFlatRequired proto; \ + UNIT_ASSERT_EXCEPTION(Json2Proto(json, proto), yexception); \ + } #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD -} // TestFlatRequired +} // TestFlatRequired Y_UNIT_TEST(TestNameGenerator) { - TJson2ProtoConfig cfg; - cfg.SetNameGenerator([](const NProtoBuf::FieldDescriptor&) { return "42"; }); + TJson2ProtoConfig cfg; + cfg.SetNameGenerator([](const NProtoBuf::FieldDescriptor&) { return "42"; }); - TNameGeneratorType proto; + TNameGeneratorType proto; Json2Proto(TStringBuf(R"({"42":42})"), proto, cfg); - TNameGeneratorType expected; - expected.SetField(42); - - UNIT_ASSERT_PROTOS_EQUAL(expected, proto); -} + TNameGeneratorType expected; + expected.SetField(42); + UNIT_ASSERT_PROTOS_EQUAL(expected, proto); +} + Y_UNIT_TEST(TestFlatNoCheckRequired) { - { - const NJson::TJsonValue& json = CreateFlatJson(); - TFlatRequired proto; - Json2Proto(json, proto); - TFlatRequired modelProto; - FillFlatProto(&modelProto); - UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); + { + const NJson::TJsonValue& json = CreateFlatJson(); + TFlatRequired proto; + Json2Proto(json, proto); + TFlatRequired modelProto; + FillFlatProto(&modelProto); + UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); } - TJson2ProtoConfig cfg; - cfg.CheckRequiredFields = false; - - // Try to skip each field -#define DEFINE_FIELD(name, value) \ - { \ - THashSet<TString> skippedField; \ - skippedField.insert(#name); \ - const NJson::TJsonValue& json = CreateFlatJson(skippedField); \ - TFlatRequired proto; \ - UNIT_ASSERT_NO_EXCEPTION(Json2Proto(json, proto, cfg)); \ - } + TJson2ProtoConfig cfg; + cfg.CheckRequiredFields = false; + + // Try to skip each field +#define DEFINE_FIELD(name, value) \ + { \ + THashSet<TString> skippedField; \ + skippedField.insert(#name); \ + const NJson::TJsonValue& json = CreateFlatJson(skippedField); \ + TFlatRequired proto; \ + UNIT_ASSERT_NO_EXCEPTION(Json2Proto(json, proto, cfg)); \ + } #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD -} // TestFlatNoCheckRequired +} // TestFlatNoCheckRequired Y_UNIT_TEST(TestFlatRepeated){ - {const NJson::TJsonValue& json = CreateRepeatedFlatJson(); -TFlatRepeated proto; -Json2Proto(json, proto); -TFlatRepeated modelProto; -FillRepeatedProto(&modelProto); -UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); -} - -// Try to skip each field -#define DEFINE_REPEATED_FIELD(name, ...) \ - { \ - THashSet<TString> skippedField; \ - skippedField.insert(#name); \ - const NJson::TJsonValue& json = CreateRepeatedFlatJson(skippedField); \ - TFlatRepeated proto; \ - Json2Proto(json, proto); \ - TFlatRepeated modelProto; \ - FillRepeatedProto(&modelProto, skippedField); \ - UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); \ - } + {const NJson::TJsonValue& json = CreateRepeatedFlatJson(); +TFlatRepeated proto; +Json2Proto(json, proto); +TFlatRepeated modelProto; +FillRepeatedProto(&modelProto); +UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); +} + +// Try to skip each field +#define DEFINE_REPEATED_FIELD(name, ...) \ + { \ + THashSet<TString> skippedField; \ + skippedField.insert(#name); \ + const NJson::TJsonValue& json = CreateRepeatedFlatJson(skippedField); \ + TFlatRepeated proto; \ + Json2Proto(json, proto); \ + TFlatRepeated modelProto; \ + FillRepeatedProto(&modelProto, skippedField); \ + UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); \ + } #include <library/cpp/protobuf/json/ut/repeated_fields.incl> #undef DEFINE_REPEATED_FIELD -} // TestFlatRepeated +} // TestFlatRepeated Y_UNIT_TEST(TestCompositeOptional){ - {const NJson::TJsonValue& json = CreateCompositeJson(); -TCompositeOptional proto; -Json2Proto(json, proto); -TCompositeOptional modelProto; -FillCompositeProto(&modelProto); -UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); -} - -// Try to skip each field -#define DEFINE_FIELD(name, value) \ - { \ - THashSet<TString> skippedField; \ - skippedField.insert(#name); \ - const NJson::TJsonValue& json = CreateCompositeJson(skippedField); \ - TCompositeOptional proto; \ - Json2Proto(json, proto); \ - TCompositeOptional modelProto; \ - FillCompositeProto(&modelProto, skippedField); \ - UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); \ - } + {const NJson::TJsonValue& json = CreateCompositeJson(); +TCompositeOptional proto; +Json2Proto(json, proto); +TCompositeOptional modelProto; +FillCompositeProto(&modelProto); +UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); +} + +// Try to skip each field +#define DEFINE_FIELD(name, value) \ + { \ + THashSet<TString> skippedField; \ + skippedField.insert(#name); \ + const NJson::TJsonValue& json = CreateCompositeJson(skippedField); \ + TCompositeOptional proto; \ + Json2Proto(json, proto); \ + TCompositeOptional modelProto; \ + FillCompositeProto(&modelProto, skippedField); \ + UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); \ + } #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD -} // TestCompositeOptional +} // TestCompositeOptional Y_UNIT_TEST(TestCompositeOptionalStringBuf){ - {NJson::TJsonValue json = CreateCompositeJson(); -json["Part"]["Double"] = 42.5; -TCompositeOptional proto; -Json2Proto(JsonValueToString(json), proto); -TCompositeOptional modelProto; -FillCompositeProto(&modelProto); -modelProto.MutablePart()->SetDouble(42.5); -UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); -} - -// Try to skip each field -#define DEFINE_FIELD(name, value) \ - { \ - THashSet<TString> skippedField; \ - skippedField.insert(#name); \ - NJson::TJsonValue json = CreateCompositeJson(skippedField); \ - if (json["Part"].Has("Double")) { \ - json["Part"]["Double"] = 42.5; \ - } \ - TCompositeOptional proto; \ - Json2Proto(JsonValueToString(json), proto); \ - TCompositeOptional modelProto; \ - FillCompositeProto(&modelProto, skippedField); \ - if (modelProto.GetPart().HasDouble()) { \ - modelProto.MutablePart()->SetDouble(42.5); \ - } \ - UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); \ - } + {NJson::TJsonValue json = CreateCompositeJson(); +json["Part"]["Double"] = 42.5; +TCompositeOptional proto; +Json2Proto(JsonValueToString(json), proto); +TCompositeOptional modelProto; +FillCompositeProto(&modelProto); +modelProto.MutablePart()->SetDouble(42.5); +UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); +} + +// Try to skip each field +#define DEFINE_FIELD(name, value) \ + { \ + THashSet<TString> skippedField; \ + skippedField.insert(#name); \ + NJson::TJsonValue json = CreateCompositeJson(skippedField); \ + if (json["Part"].Has("Double")) { \ + json["Part"]["Double"] = 42.5; \ + } \ + TCompositeOptional proto; \ + Json2Proto(JsonValueToString(json), proto); \ + TCompositeOptional modelProto; \ + FillCompositeProto(&modelProto, skippedField); \ + if (modelProto.GetPart().HasDouble()) { \ + modelProto.MutablePart()->SetDouble(42.5); \ + } \ + UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); \ + } #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD -} // TestCompositeOptionalStringBuf +} // TestCompositeOptionalStringBuf Y_UNIT_TEST(TestCompositeRequired) { - { - const NJson::TJsonValue& json = CreateCompositeJson(); - TCompositeRequired proto; - Json2Proto(json, proto); - TCompositeRequired modelProto; - FillCompositeProto(&modelProto); - UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); - } - - { - NJson::TJsonValue json; - TCompositeRequired proto; - UNIT_ASSERT_EXCEPTION(Json2Proto(json, proto), yexception); - } -} // TestCompositeRequired + { + const NJson::TJsonValue& json = CreateCompositeJson(); + TCompositeRequired proto; + Json2Proto(json, proto); + TCompositeRequired modelProto; + FillCompositeProto(&modelProto); + UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); + } + + { + NJson::TJsonValue json; + TCompositeRequired proto; + UNIT_ASSERT_EXCEPTION(Json2Proto(json, proto), yexception); + } +} // TestCompositeRequired Y_UNIT_TEST(TestCompositeRepeated) { - { - NJson::TJsonValue json; - NJson::TJsonValue array; - array.AppendValue(CreateFlatJson()); - json.InsertValue("Part", array); - - TCompositeRepeated proto; - Json2Proto(json, proto); - - TFlatOptional partModelProto; - FillFlatProto(&partModelProto); - TCompositeRepeated modelProto; - modelProto.AddPart()->CopyFrom(partModelProto); - - UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); - } - - { - // Array of messages with each field skipped - TCompositeRepeated modelProto; - NJson::TJsonValue array; - -#define DEFINE_REPEATED_FIELD(name, ...) \ - { \ - THashSet<TString> skippedField; \ - skippedField.insert(#name); \ - TFlatOptional partModelProto; \ - FillFlatProto(&partModelProto, skippedField); \ - modelProto.AddPart()->CopyFrom(partModelProto); \ - array.AppendValue(CreateFlatJson(skippedField)); \ - } + { + NJson::TJsonValue json; + NJson::TJsonValue array; + array.AppendValue(CreateFlatJson()); + json.InsertValue("Part", array); + + TCompositeRepeated proto; + Json2Proto(json, proto); + + TFlatOptional partModelProto; + FillFlatProto(&partModelProto); + TCompositeRepeated modelProto; + modelProto.AddPart()->CopyFrom(partModelProto); + + UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); + } + + { + // Array of messages with each field skipped + TCompositeRepeated modelProto; + NJson::TJsonValue array; + +#define DEFINE_REPEATED_FIELD(name, ...) \ + { \ + THashSet<TString> skippedField; \ + skippedField.insert(#name); \ + TFlatOptional partModelProto; \ + FillFlatProto(&partModelProto, skippedField); \ + modelProto.AddPart()->CopyFrom(partModelProto); \ + array.AppendValue(CreateFlatJson(skippedField)); \ + } #include <library/cpp/protobuf/json/ut/repeated_fields.incl> #undef DEFINE_REPEATED_FIELD - NJson::TJsonValue json; - json.InsertValue("Part", array); + NJson::TJsonValue json; + json.InsertValue("Part", array); - TCompositeRepeated proto; - Json2Proto(json, proto); + TCompositeRepeated proto; + Json2Proto(json, proto); - UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); - } -} // TestCompositeRepeated + UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); + } +} // TestCompositeRepeated Y_UNIT_TEST(TestInvalidEnum) { - { - NJson::TJsonValue json; - json.InsertValue("Enum", "E_100"); - TFlatOptional proto; - UNIT_ASSERT_EXCEPTION(Json2Proto(json, proto), yexception); - } - - { - NJson::TJsonValue json; - json.InsertValue("Enum", 100); - TFlatOptional proto; - UNIT_ASSERT_EXCEPTION(Json2Proto(json, proto), yexception); + { + NJson::TJsonValue json; + json.InsertValue("Enum", "E_100"); + TFlatOptional proto; + UNIT_ASSERT_EXCEPTION(Json2Proto(json, proto), yexception); + } + + { + NJson::TJsonValue json; + json.InsertValue("Enum", 100); + TFlatOptional proto; + UNIT_ASSERT_EXCEPTION(Json2Proto(json, proto), yexception); } -} +} Y_UNIT_TEST(TestFieldNameMode) { - // Original case 1 - { - TString modelStr(R"_({"String":"value"})_"); + // Original case 1 + { + TString modelStr(R"_({"String":"value"})_"); - TFlatOptional proto; - TJson2ProtoConfig config; + TFlatOptional proto; + TJson2ProtoConfig config; - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); - UNIT_ASSERT(proto.GetString() == "value"); - } + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); + UNIT_ASSERT(proto.GetString() == "value"); + } - // Original case 2 - { - TString modelStr(R"_({"String":"value"})_"); + // Original case 2 + { + TString modelStr(R"_({"String":"value"})_"); - TFlatOptional proto; - TJson2ProtoConfig config; - config.FieldNameMode = TJson2ProtoConfig::FieldNameOriginalCase; + TFlatOptional proto; + TJson2ProtoConfig config; + config.FieldNameMode = TJson2ProtoConfig::FieldNameOriginalCase; - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); - UNIT_ASSERT(proto.GetString() == "value"); - } + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); + UNIT_ASSERT(proto.GetString() == "value"); + } - // Lowercase - { - TString modelStr(R"_({"string":"value"})_"); + // Lowercase + { + TString modelStr(R"_({"string":"value"})_"); - TFlatOptional proto; - TJson2ProtoConfig config; - config.FieldNameMode = TJson2ProtoConfig::FieldNameLowerCase; + TFlatOptional proto; + TJson2ProtoConfig config; + config.FieldNameMode = TJson2ProtoConfig::FieldNameLowerCase; - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); - UNIT_ASSERT(proto.GetString() == "value"); - } + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); + UNIT_ASSERT(proto.GetString() == "value"); + } - // Uppercase - { - TString modelStr(R"_({"STRING":"value"})_"); + // Uppercase + { + TString modelStr(R"_({"STRING":"value"})_"); - TFlatOptional proto; - TJson2ProtoConfig config; - config.FieldNameMode = TJson2ProtoConfig::FieldNameUpperCase; + TFlatOptional proto; + TJson2ProtoConfig config; + config.FieldNameMode = TJson2ProtoConfig::FieldNameUpperCase; - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); - UNIT_ASSERT(proto.GetString() == "value"); - } + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); + UNIT_ASSERT(proto.GetString() == "value"); + } - // Camelcase - { - TString modelStr(R"_({"string":"value"})_"); + // Camelcase + { + TString modelStr(R"_({"string":"value"})_"); - TFlatOptional proto; - TJson2ProtoConfig config; - config.FieldNameMode = TJson2ProtoConfig::FieldNameCamelCase; + TFlatOptional proto; + TJson2ProtoConfig config; + config.FieldNameMode = TJson2ProtoConfig::FieldNameCamelCase; - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); - UNIT_ASSERT(proto.GetString() == "value"); - } - { - TString modelStr(R"_({"oneString":"value"})_"); + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); + UNIT_ASSERT(proto.GetString() == "value"); + } + { + TString modelStr(R"_({"oneString":"value"})_"); - TFlatOptional proto; - TJson2ProtoConfig config; - config.FieldNameMode = TJson2ProtoConfig::FieldNameCamelCase; + TFlatOptional proto; + TJson2ProtoConfig config; + config.FieldNameMode = TJson2ProtoConfig::FieldNameCamelCase; - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); - UNIT_ASSERT(proto.GetOneString() == "value"); - } - { - TString modelStr(R"_({"oneTwoString":"value"})_"); + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); + UNIT_ASSERT(proto.GetOneString() == "value"); + } + { + TString modelStr(R"_({"oneTwoString":"value"})_"); - TFlatOptional proto; - TJson2ProtoConfig config; - config.FieldNameMode = TJson2ProtoConfig::FieldNameCamelCase; + TFlatOptional proto; + TJson2ProtoConfig config; + config.FieldNameMode = TJson2ProtoConfig::FieldNameCamelCase; - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); - UNIT_ASSERT(proto.GetOneTwoString() == "value"); - } + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); + UNIT_ASSERT(proto.GetOneTwoString() == "value"); + } // snake_case { @@ -430,95 +430,95 @@ Y_UNIT_TEST(TestFieldNameMode) { UNIT_ASSERT(proto.GetOneTwoString() == "value"); } - // Original case, repeated - { - TString modelStr(R"_({"I32":[1,2]})_"); - - TFlatRepeated proto; - TJson2ProtoConfig config; - config.FieldNameMode = TJson2ProtoConfig::FieldNameOriginalCase; - - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatRepeated>(modelStr, config)); - UNIT_ASSERT(proto.I32Size() == 2); - UNIT_ASSERT(proto.GetI32(0) == 1); - UNIT_ASSERT(proto.GetI32(1) == 2); - } - - // Lower case, repeated - { - TString modelStr(R"_({"i32":[1,2]})_"); - - TFlatRepeated proto; - TJson2ProtoConfig config; - config.FieldNameMode = TJson2ProtoConfig::FieldNameLowerCase; - - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatRepeated>(modelStr, config)); - UNIT_ASSERT(proto.I32Size() == 2); - UNIT_ASSERT(proto.GetI32(0) == 1); - UNIT_ASSERT(proto.GetI32(1) == 2); - } - - // UseJsonName - { - // FIXME(CONTRIB-139): since protobuf 3.1, Def_upper json name is - // "DefUpper", but until kernel/ugc/schema and yweb/yasap/pdb are + // Original case, repeated + { + TString modelStr(R"_({"I32":[1,2]})_"); + + TFlatRepeated proto; + TJson2ProtoConfig config; + config.FieldNameMode = TJson2ProtoConfig::FieldNameOriginalCase; + + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatRepeated>(modelStr, config)); + UNIT_ASSERT(proto.I32Size() == 2); + UNIT_ASSERT(proto.GetI32(0) == 1); + UNIT_ASSERT(proto.GetI32(1) == 2); + } + + // Lower case, repeated + { + TString modelStr(R"_({"i32":[1,2]})_"); + + TFlatRepeated proto; + TJson2ProtoConfig config; + config.FieldNameMode = TJson2ProtoConfig::FieldNameLowerCase; + + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatRepeated>(modelStr, config)); + UNIT_ASSERT(proto.I32Size() == 2); + UNIT_ASSERT(proto.GetI32(0) == 1); + UNIT_ASSERT(proto.GetI32(1) == 2); + } + + // UseJsonName + { + // FIXME(CONTRIB-139): since protobuf 3.1, Def_upper json name is + // "DefUpper", but until kernel/ugc/schema and yweb/yasap/pdb are // updated, library/cpp/protobuf/json preserves compatibility with - // protobuf 3.0 by lowercasing default names, making it "defUpper". - TString modelStr(R"_({"My-Upper":1,"my-lower":2,"defUpper":3,"defLower":4})_"); - - TWithJsonName proto; - TJson2ProtoConfig config; - config.SetUseJsonName(true); - - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TWithJsonName>(modelStr, config)); - UNIT_ASSERT_EQUAL(proto.Getmy_upper(), 1); - UNIT_ASSERT_EQUAL(proto.GetMy_lower(), 2); - UNIT_ASSERT_EQUAL(proto.GetDef_upper(), 3); - UNIT_ASSERT_EQUAL(proto.Getdef_lower(), 4); - } - - // FieldNameMode with UseJsonName - { - TJson2ProtoConfig config; - config.SetFieldNameMode(TJson2ProtoConfig::FieldNameLowerCase); - UNIT_ASSERT_EXCEPTION_CONTAINS( - config.SetUseJsonName(true), yexception, "mutually exclusive"); - } - { - TJson2ProtoConfig config; - config.SetUseJsonName(true); - UNIT_ASSERT_EXCEPTION_CONTAINS( - config.SetFieldNameMode(TJson2ProtoConfig::FieldNameLowerCase), yexception, "mutually exclusive"); - } -} // TestFieldNameMode - -class TStringTransform: public IStringTransform { -public: - int GetType() const override { - return 0; + // protobuf 3.0 by lowercasing default names, making it "defUpper". + TString modelStr(R"_({"My-Upper":1,"my-lower":2,"defUpper":3,"defLower":4})_"); + + TWithJsonName proto; + TJson2ProtoConfig config; + config.SetUseJsonName(true); + + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TWithJsonName>(modelStr, config)); + UNIT_ASSERT_EQUAL(proto.Getmy_upper(), 1); + UNIT_ASSERT_EQUAL(proto.GetMy_lower(), 2); + UNIT_ASSERT_EQUAL(proto.GetDef_upper(), 3); + UNIT_ASSERT_EQUAL(proto.Getdef_lower(), 4); + } + + // FieldNameMode with UseJsonName + { + TJson2ProtoConfig config; + config.SetFieldNameMode(TJson2ProtoConfig::FieldNameLowerCase); + UNIT_ASSERT_EXCEPTION_CONTAINS( + config.SetUseJsonName(true), yexception, "mutually exclusive"); + } + { + TJson2ProtoConfig config; + config.SetUseJsonName(true); + UNIT_ASSERT_EXCEPTION_CONTAINS( + config.SetFieldNameMode(TJson2ProtoConfig::FieldNameLowerCase), yexception, "mutually exclusive"); + } +} // TestFieldNameMode + +class TStringTransform: public IStringTransform { +public: + int GetType() const override { + return 0; + } + void Transform(TString& str) const override { + str = "transformed_any"; + } +}; + +class TBytesTransform: public IStringTransform { +public: + int GetType() const override { + return 0; } - void Transform(TString& str) const override { - str = "transformed_any"; - } -}; - -class TBytesTransform: public IStringTransform { -public: - int GetType() const override { - return 0; - } - void Transform(TString&) const override { - } - void TransformBytes(TString& str) const override { - str = "transformed_bytes"; - } -}; + void Transform(TString&) const override { + } + void TransformBytes(TString& str) const override { + str = "transformed_bytes"; + } +}; Y_UNIT_TEST(TestInvalidJson) { - NJson::TJsonValue val{"bad value"}; - TFlatOptional proto; - UNIT_ASSERT_EXCEPTION(Json2Proto(val, proto), yexception); -} + NJson::TJsonValue val{"bad value"}; + TFlatOptional proto; + UNIT_ASSERT_EXCEPTION(Json2Proto(val, proto), yexception); +} Y_UNIT_TEST(TestInvalidRepeatedFieldWithMapAsObject) { TCompositeRepeated proto; @@ -528,149 +528,149 @@ Y_UNIT_TEST(TestInvalidRepeatedFieldWithMapAsObject) { } Y_UNIT_TEST(TestStringTransforms) { - // Check that strings and bytes are transformed - { - TString modelStr(R"_({"String":"value_str", "Bytes": "value_bytes"})_"); - - TFlatOptional proto; - TJson2ProtoConfig config; - config.AddStringTransform(new TStringTransform); - - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); - UNIT_ASSERT(proto.GetString() == "transformed_any"); - UNIT_ASSERT(proto.GetBytes() == "transformed_any"); - } - - // Check that bytes are transformed, strings are left intact - { - TString modelStr(R"_({"String":"value_str", "Bytes": "value_bytes"})_"); - - TFlatOptional proto; - TJson2ProtoConfig config; - config.AddStringTransform(new TBytesTransform); - - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); - UNIT_ASSERT(proto.GetString() == "value_str"); - UNIT_ASSERT(proto.GetBytes() == "transformed_bytes"); - } - - // Check that repeated bytes are transformed, repeated strings are left intact - { - TString modelStr(R"_({"String":["value_str", "str2"], "Bytes": ["value_bytes", "bytes2"]})_"); - - TFlatRepeated proto; - TJson2ProtoConfig config; - config.AddStringTransform(new TBytesTransform); - - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatRepeated>(modelStr, config)); - UNIT_ASSERT(proto.StringSize() == 2); - UNIT_ASSERT(proto.GetString(0) == "value_str"); - UNIT_ASSERT(proto.GetString(1) == "str2"); - UNIT_ASSERT(proto.BytesSize() == 2); - UNIT_ASSERT(proto.GetBytes(0) == "transformed_bytes"); - UNIT_ASSERT(proto.GetBytes(1) == "transformed_bytes"); - } - - // Check that bytes are transformed, strings are left intact in composed messages - { - TString modelStr(R"_({"Part": {"String":"value_str", "Bytes": "value_bytes"}})_"); - - TCompositeOptional proto; - TJson2ProtoConfig config; - config.AddStringTransform(new TBytesTransform); - - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TCompositeOptional>(modelStr, config)); - UNIT_ASSERT(proto.GetPart().GetString() == "value_str"); - UNIT_ASSERT(proto.GetPart().GetBytes() == "transformed_bytes"); - } -} // TestStringTransforms - + // Check that strings and bytes are transformed + { + TString modelStr(R"_({"String":"value_str", "Bytes": "value_bytes"})_"); + + TFlatOptional proto; + TJson2ProtoConfig config; + config.AddStringTransform(new TStringTransform); + + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); + UNIT_ASSERT(proto.GetString() == "transformed_any"); + UNIT_ASSERT(proto.GetBytes() == "transformed_any"); + } + + // Check that bytes are transformed, strings are left intact + { + TString modelStr(R"_({"String":"value_str", "Bytes": "value_bytes"})_"); + + TFlatOptional proto; + TJson2ProtoConfig config; + config.AddStringTransform(new TBytesTransform); + + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatOptional>(modelStr, config)); + UNIT_ASSERT(proto.GetString() == "value_str"); + UNIT_ASSERT(proto.GetBytes() == "transformed_bytes"); + } + + // Check that repeated bytes are transformed, repeated strings are left intact + { + TString modelStr(R"_({"String":["value_str", "str2"], "Bytes": ["value_bytes", "bytes2"]})_"); + + TFlatRepeated proto; + TJson2ProtoConfig config; + config.AddStringTransform(new TBytesTransform); + + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TFlatRepeated>(modelStr, config)); + UNIT_ASSERT(proto.StringSize() == 2); + UNIT_ASSERT(proto.GetString(0) == "value_str"); + UNIT_ASSERT(proto.GetString(1) == "str2"); + UNIT_ASSERT(proto.BytesSize() == 2); + UNIT_ASSERT(proto.GetBytes(0) == "transformed_bytes"); + UNIT_ASSERT(proto.GetBytes(1) == "transformed_bytes"); + } + + // Check that bytes are transformed, strings are left intact in composed messages + { + TString modelStr(R"_({"Part": {"String":"value_str", "Bytes": "value_bytes"}})_"); + + TCompositeOptional proto; + TJson2ProtoConfig config; + config.AddStringTransform(new TBytesTransform); + + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TCompositeOptional>(modelStr, config)); + UNIT_ASSERT(proto.GetPart().GetString() == "value_str"); + UNIT_ASSERT(proto.GetPart().GetBytes() == "transformed_bytes"); + } +} // TestStringTransforms + Y_UNIT_TEST(TestCastFromString) { - // single fields - { - NJson::TJsonValue json; + // single fields + { + NJson::TJsonValue json; #define DEFINE_FIELD(name, value) \ - json.InsertValue(#name, ConvertToString(value)); + json.InsertValue(#name, ConvertToString(value)); #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD - TFlatOptional proto; - UNIT_ASSERT_EXCEPTION_CONTAINS(Json2Proto(json, proto), yexception, "Invalid type"); - - TJson2ProtoConfig config; - config.SetCastFromString(true); - Json2Proto(json, proto, config); - - TFlatOptional modelProto; - FillFlatProto(&modelProto); - UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); - } - - // repeated fields - { - NJson::TJsonValue json; -#define DEFINE_REPEATED_FIELD(name, type, ...) \ - { \ - type values[] = {__VA_ARGS__}; \ - NJson::TJsonValue array(NJson::JSON_ARRAY); \ - for (size_t i = 0, end = Y_ARRAY_SIZE(values); i < end; ++i) { \ - array.AppendValue(ConvertToString(values[i])); \ - } \ - json.InsertValue(#name, array); \ - } + TFlatOptional proto; + UNIT_ASSERT_EXCEPTION_CONTAINS(Json2Proto(json, proto), yexception, "Invalid type"); + + TJson2ProtoConfig config; + config.SetCastFromString(true); + Json2Proto(json, proto, config); + + TFlatOptional modelProto; + FillFlatProto(&modelProto); + UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); + } + + // repeated fields + { + NJson::TJsonValue json; +#define DEFINE_REPEATED_FIELD(name, type, ...) \ + { \ + type values[] = {__VA_ARGS__}; \ + NJson::TJsonValue array(NJson::JSON_ARRAY); \ + for (size_t i = 0, end = Y_ARRAY_SIZE(values); i < end; ++i) { \ + array.AppendValue(ConvertToString(values[i])); \ + } \ + json.InsertValue(#name, array); \ + } #include <library/cpp/protobuf/json/ut/repeated_fields.incl> #undef DEFINE_REPEATED_FIELD - TFlatRepeated proto; - UNIT_ASSERT_EXCEPTION_CONTAINS(Json2Proto(json, proto), yexception, "Invalid type"); + TFlatRepeated proto; + UNIT_ASSERT_EXCEPTION_CONTAINS(Json2Proto(json, proto), yexception, "Invalid type"); - TJson2ProtoConfig config; - config.SetCastFromString(true); - Json2Proto(json, proto, config); + TJson2ProtoConfig config; + config.SetCastFromString(true); + Json2Proto(json, proto, config); - TFlatRepeated modelProto; - FillRepeatedProto(&modelProto); - UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); - } -} // TestCastFromString + TFlatRepeated modelProto; + FillRepeatedProto(&modelProto); + UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); + } +} // TestCastFromString Y_UNIT_TEST(TestMap) { - TMapType modelProto; + TMapType modelProto; - auto& items = *modelProto.MutableItems(); - items["key1"] = "value1"; - items["key2"] = "value2"; - items["key3"] = "value3"; + auto& items = *modelProto.MutableItems(); + items["key1"] = "value1"; + items["key2"] = "value2"; + items["key3"] = "value3"; - TString modelStr(R"_({"Items":[{"key":"key3","value":"value3"},{"key":"key2","value":"value2"},{"key":"key1","value":"value1"}]})_"); + TString modelStr(R"_({"Items":[{"key":"key3","value":"value3"},{"key":"key2","value":"value2"},{"key":"key1","value":"value1"}]})_"); - TJson2ProtoConfig config; - TMapType proto; - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TMapType>(modelStr, config)); + TJson2ProtoConfig config; + TMapType proto; + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TMapType>(modelStr, config)); - UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); -} // TestMap + UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); +} // TestMap Y_UNIT_TEST(TestCastRobust) { - NJson::TJsonValue json; - json["I32"] = "5"; - json["Bool"] = 1; - json["String"] = 6; - json["Double"] = 8; - TFlatOptional proto; - UNIT_ASSERT_EXCEPTION_CONTAINS(Json2Proto(json, proto), yexception, "Invalid type"); - - TJson2ProtoConfig config; - config.SetCastRobust(true); - Json2Proto(json, proto, config); - - TFlatOptional expected; - expected.SetI32(5); - expected.SetBool(true); - expected.SetString("6"); - expected.SetDouble(8); - UNIT_ASSERT_PROTOS_EQUAL(proto, expected); -} + NJson::TJsonValue json; + json["I32"] = "5"; + json["Bool"] = 1; + json["String"] = 6; + json["Double"] = 8; + TFlatOptional proto; + UNIT_ASSERT_EXCEPTION_CONTAINS(Json2Proto(json, proto), yexception, "Invalid type"); + + TJson2ProtoConfig config; + config.SetCastRobust(true); + Json2Proto(json, proto, config); + + TFlatOptional expected; + expected.SetI32(5); + expected.SetBool(true); + expected.SetString("6"); + expected.SetDouble(8); + UNIT_ASSERT_PROTOS_EQUAL(proto, expected); +} Y_UNIT_TEST(TestVectorizeScalars) { NJson::TJsonValue json; @@ -742,165 +742,165 @@ Y_UNIT_TEST(TestValueVectorizer) { } Y_UNIT_TEST(TestMapAsObject) { - TMapType modelProto; + TMapType modelProto; - auto& items = *modelProto.MutableItems(); - items["key1"] = "value1"; - items["key2"] = "value2"; - items["key3"] = "value3"; + auto& items = *modelProto.MutableItems(); + items["key1"] = "value1"; + items["key2"] = "value2"; + items["key3"] = "value3"; - TString modelStr(R"_({"Items":{"key1":"value1","key2":"value2","key3":"value3"}})_"); + TString modelStr(R"_({"Items":{"key1":"value1","key2":"value2","key3":"value3"}})_"); - TJson2ProtoConfig config; - config.MapAsObject = true; - TMapType proto; - UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TMapType>(modelStr, config)); + TJson2ProtoConfig config; + config.MapAsObject = true; + TMapType proto; + UNIT_ASSERT_NO_EXCEPTION(proto = Json2Proto<TMapType>(modelStr, config)); - UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); -} // TestMapAsObject + UNIT_ASSERT_PROTOS_EQUAL(proto, modelProto); +} // TestMapAsObject Y_UNIT_TEST(TestComplexMapAsObject_I32) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableI32(); - items[1] = 1; - items[-2] = -2; - items[3] = 3; - }, - R"_({"I32":{"1":1,"-2":-2,"3":3}})_"); -} // TestComplexMapAsObject_I32 + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableI32(); + items[1] = 1; + items[-2] = -2; + items[3] = 3; + }, + R"_({"I32":{"1":1,"-2":-2,"3":3}})_"); +} // TestComplexMapAsObject_I32 Y_UNIT_TEST(TestComplexMapAsObject_I64) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableI64(); - items[2147483649L] = 2147483649L; - items[-2147483650L] = -2147483650L; - items[2147483651L] = 2147483651L; - }, - R"_({"I64":{"2147483649":2147483649,"-2147483650":-2147483650,"2147483651":2147483651}})_"); -} // TestComplexMapAsObject_I64 + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableI64(); + items[2147483649L] = 2147483649L; + items[-2147483650L] = -2147483650L; + items[2147483651L] = 2147483651L; + }, + R"_({"I64":{"2147483649":2147483649,"-2147483650":-2147483650,"2147483651":2147483651}})_"); +} // TestComplexMapAsObject_I64 Y_UNIT_TEST(TestComplexMapAsObject_UI32) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableUI32(); - items[1073741825U] = 1073741825U; - items[1073741826U] = 1073741826U; - items[1073741827U] = 1073741827U; - }, - R"_({"UI32":{"1073741825":1073741825,"1073741826":1073741826,"1073741827":1073741827}})_"); -} // TestComplexMapAsObject_UI32 + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableUI32(); + items[1073741825U] = 1073741825U; + items[1073741826U] = 1073741826U; + items[1073741827U] = 1073741827U; + }, + R"_({"UI32":{"1073741825":1073741825,"1073741826":1073741826,"1073741827":1073741827}})_"); +} // TestComplexMapAsObject_UI32 Y_UNIT_TEST(TestComplexMapAsObject_UI64) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableUI64(); - items[9223372036854775809UL] = 9223372036854775809UL; - items[9223372036854775810UL] = 9223372036854775810UL; - items[9223372036854775811UL] = 9223372036854775811UL; - }, - R"_({"UI64":{"9223372036854775809":9223372036854775809,"9223372036854775810":9223372036854775810,"9223372036854775811":9223372036854775811}})_"); -} // TestComplexMapAsObject_UI64 + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableUI64(); + items[9223372036854775809UL] = 9223372036854775809UL; + items[9223372036854775810UL] = 9223372036854775810UL; + items[9223372036854775811UL] = 9223372036854775811UL; + }, + R"_({"UI64":{"9223372036854775809":9223372036854775809,"9223372036854775810":9223372036854775810,"9223372036854775811":9223372036854775811}})_"); +} // TestComplexMapAsObject_UI64 Y_UNIT_TEST(TestComplexMapAsObject_SI32) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableSI32(); - items[1] = 1; - items[-2] = -2; - items[3] = 3; - }, - R"_({"SI32":{"1":1,"-2":-2,"3":3}})_"); -} // TestComplexMapAsObject_SI32 + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableSI32(); + items[1] = 1; + items[-2] = -2; + items[3] = 3; + }, + R"_({"SI32":{"1":1,"-2":-2,"3":3}})_"); +} // TestComplexMapAsObject_SI32 Y_UNIT_TEST(TestComplexMapAsObject_SI64) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableSI64(); - items[2147483649L] = 2147483649L; - items[-2147483650L] = -2147483650L; - items[2147483651L] = 2147483651L; - }, - R"_({"SI64":{"2147483649":2147483649,"-2147483650":-2147483650,"2147483651":2147483651}})_"); -} // TestComplexMapAsObject_SI64 + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableSI64(); + items[2147483649L] = 2147483649L; + items[-2147483650L] = -2147483650L; + items[2147483651L] = 2147483651L; + }, + R"_({"SI64":{"2147483649":2147483649,"-2147483650":-2147483650,"2147483651":2147483651}})_"); +} // TestComplexMapAsObject_SI64 Y_UNIT_TEST(TestComplexMapAsObject_FI32) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableFI32(); - items[1073741825U] = 1073741825U; - items[1073741826U] = 1073741826U; - items[1073741827U] = 1073741827U; - }, - R"_({"FI32":{"1073741825":1073741825,"1073741826":1073741826,"1073741827":1073741827}})_"); -} // TestComplexMapAsObject_FI32 + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableFI32(); + items[1073741825U] = 1073741825U; + items[1073741826U] = 1073741826U; + items[1073741827U] = 1073741827U; + }, + R"_({"FI32":{"1073741825":1073741825,"1073741826":1073741826,"1073741827":1073741827}})_"); +} // TestComplexMapAsObject_FI32 Y_UNIT_TEST(TestComplexMapAsObject_FI64) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableFI64(); - items[9223372036854775809UL] = 9223372036854775809UL; - items[9223372036854775810UL] = 9223372036854775810UL; - items[9223372036854775811UL] = 9223372036854775811UL; - }, - R"_({"FI64":{"9223372036854775809":9223372036854775809,"9223372036854775810":9223372036854775810,"9223372036854775811":9223372036854775811}})_"); -} // TestComplexMapAsObject_FI64 + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableFI64(); + items[9223372036854775809UL] = 9223372036854775809UL; + items[9223372036854775810UL] = 9223372036854775810UL; + items[9223372036854775811UL] = 9223372036854775811UL; + }, + R"_({"FI64":{"9223372036854775809":9223372036854775809,"9223372036854775810":9223372036854775810,"9223372036854775811":9223372036854775811}})_"); +} // TestComplexMapAsObject_FI64 Y_UNIT_TEST(TestComplexMapAsObject_SFI32) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableSFI32(); - items[1] = 1; - items[-2] = -2; - items[3] = 3; - }, - R"_({"SFI32":{"1":1,"-2":-2,"3":3}})_"); -} // TestComplexMapAsObject_SFI32 + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableSFI32(); + items[1] = 1; + items[-2] = -2; + items[3] = 3; + }, + R"_({"SFI32":{"1":1,"-2":-2,"3":3}})_"); +} // TestComplexMapAsObject_SFI32 Y_UNIT_TEST(TestComplexMapAsObject_SFI64) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableSFI64(); - items[2147483649L] = 2147483649L; - items[-2147483650L] = -2147483650L; - items[2147483651L] = 2147483651L; - }, - R"_({"SFI64":{"2147483649":2147483649,"-2147483650":-2147483650,"2147483651":2147483651}})_"); -} // TestComplexMapAsObject_SFI64 + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableSFI64(); + items[2147483649L] = 2147483649L; + items[-2147483650L] = -2147483650L; + items[2147483651L] = 2147483651L; + }, + R"_({"SFI64":{"2147483649":2147483649,"-2147483650":-2147483650,"2147483651":2147483651}})_"); +} // TestComplexMapAsObject_SFI64 Y_UNIT_TEST(TestComplexMapAsObject_Bool) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableBool(); - items[true] = true; - items[false] = false; - }, - R"_({"Bool":{"true":true,"false":false}})_"); -} // TestComplexMapAsObject_Bool + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableBool(); + items[true] = true; + items[false] = false; + }, + R"_({"Bool":{"true":true,"false":false}})_"); +} // TestComplexMapAsObject_Bool Y_UNIT_TEST(TestComplexMapAsObject_String) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableString(); - items["key1"] = "value1"; - items["key2"] = "value2"; - items["key3"] = "value3"; + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableString(); + items["key1"] = "value1"; + items["key2"] = "value2"; + items["key3"] = "value3"; items[""] = "value4"; - }, + }, R"_({"String":{"key1":"value1","key2":"value2","key3":"value3","":"value4"}})_"); -} // TestComplexMapAsObject_String +} // TestComplexMapAsObject_String Y_UNIT_TEST(TestComplexMapAsObject_Enum) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableEnum(); - items["key1"] = EEnum::E_1; - items["key2"] = EEnum::E_2; - items["key3"] = EEnum::E_3; - }, - R"_({"Enum":{"key1":1,"key2":2,"key3":3}})_"); -} // TestComplexMapAsObject_Enum + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableEnum(); + items["key1"] = EEnum::E_1; + items["key2"] = EEnum::E_2; + items["key3"] = EEnum::E_3; + }, + R"_({"Enum":{"key1":1,"key2":2,"key3":3}})_"); +} // TestComplexMapAsObject_Enum Y_UNIT_TEST(TestComplexMapAsObject_EnumString) { TestComplexMapAsObject( @@ -944,49 +944,49 @@ Y_UNIT_TEST(TestComplexMapAsObject_EnumStringSnakeCaseInsensitive) { } // TestComplexMapAsObject_EnumStringCaseInsensetive Y_UNIT_TEST(TestComplexMapAsObject_Float) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableFloat(); - items["key1"] = 0.1f; - items["key2"] = 0.2f; - items["key3"] = 0.3f; - }, - R"_({"Float":{"key1":0.1,"key2":0.2,"key3":0.3}})_"); -} // TestComplexMapAsObject_Float + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableFloat(); + items["key1"] = 0.1f; + items["key2"] = 0.2f; + items["key3"] = 0.3f; + }, + R"_({"Float":{"key1":0.1,"key2":0.2,"key3":0.3}})_"); +} // TestComplexMapAsObject_Float Y_UNIT_TEST(TestComplexMapAsObject_Double) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - auto& items = *proto.MutableDouble(); - items["key1"] = 0.1L; - items["key2"] = 0.2L; - items["key3"] = 0.3L; - }, - R"_({"Double":{"key1":0.1,"key2":0.2,"key3":0.3}})_"); -} // TestComplexMapAsObject_Double + TestComplexMapAsObject( + [](TComplexMapType& proto) { + auto& items = *proto.MutableDouble(); + items["key1"] = 0.1L; + items["key2"] = 0.2L; + items["key3"] = 0.3L; + }, + R"_({"Double":{"key1":0.1,"key2":0.2,"key3":0.3}})_"); +} // TestComplexMapAsObject_Double Y_UNIT_TEST(TestComplexMapAsObject_Nested) { - TestComplexMapAsObject( - [](TComplexMapType& proto) { - TComplexMapType inner; - auto& innerItems = *inner.MutableString(); - innerItems["key"] = "value"; - auto& items = *proto.MutableNested(); - items["key1"] = inner; - items["key2"] = inner; - items["key3"] = inner; - }, - R"_({"Nested":{"key1":{"String":{"key":"value"}},"key2":{"String":{"key":"value"}},"key3":{"String":{"key":"value"}}}})_"); -} // TestComplexMapAsObject_Nested + TestComplexMapAsObject( + [](TComplexMapType& proto) { + TComplexMapType inner; + auto& innerItems = *inner.MutableString(); + innerItems["key"] = "value"; + auto& items = *proto.MutableNested(); + items["key1"] = inner; + items["key2"] = inner; + items["key3"] = inner; + }, + R"_({"Nested":{"key1":{"String":{"key":"value"}},"key2":{"String":{"key":"value"}},"key3":{"String":{"key":"value"}}}})_"); +} // TestComplexMapAsObject_Nested Y_UNIT_TEST(TestMapAsObjectConfigNotSet) { - TString modelStr(R"_({"Items":{"key":"value"}})_"); + TString modelStr(R"_({"Items":{"key":"value"}})_"); - TJson2ProtoConfig config; - UNIT_ASSERT_EXCEPTION_CONTAINS( - Json2Proto<TMapType>(modelStr, config), yexception, + TJson2ProtoConfig config; + UNIT_ASSERT_EXCEPTION_CONTAINS( + Json2Proto<TMapType>(modelStr, config), yexception, "Map as object representation is not allowed"); -} // TestMapAsObjectNotSet +} // TestMapAsObjectNotSet Y_UNIT_TEST(TestMergeFlatOptional) { const NJson::TJsonValue& json = CreateFlatJson(); diff --git a/library/cpp/protobuf/json/ut/proto.h b/library/cpp/protobuf/json/ut/proto.h index 8183bfc8e1..b9dec411bd 100644 --- a/library/cpp/protobuf/json/ut/proto.h +++ b/library/cpp/protobuf/json/ut/proto.h @@ -6,57 +6,57 @@ #include <util/system/defaults.h> namespace NProtobufJsonTest { - template <typename TProto> - inline void - FillFlatProto(TProto* proto, - const THashSet<TString>& skippedFields = THashSet<TString>()) { -#define DEFINE_FIELD(name, value) \ - if (skippedFields.find(#name) == skippedFields.end()) \ - proto->Set##name(value); + template <typename TProto> + inline void + FillFlatProto(TProto* proto, + const THashSet<TString>& skippedFields = THashSet<TString>()) { +#define DEFINE_FIELD(name, value) \ + if (skippedFields.find(#name) == skippedFields.end()) \ + proto->Set##name(value); #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD - } - - template <typename TRepeatedField, typename TValue> - inline void - AddValue(TRepeatedField* field, TValue value) { - field->Add(value); - } - - inline void - AddValue(google::protobuf::RepeatedPtrField<TString>* field, const TString& value) { - *(field->Add()) = value; - } - - inline void - FillRepeatedProto(TFlatRepeated* proto, - const THashSet<TString>& skippedFields = THashSet<TString>()) { -#define DEFINE_REPEATED_FIELD(name, type, ...) \ - if (skippedFields.find(#name) == skippedFields.end()) { \ - type values[] = {__VA_ARGS__}; \ - for (size_t i = 0, end = Y_ARRAY_SIZE(values); i < end; ++i) { \ - AddValue(proto->Mutable##name(), values[i]); \ - } \ + } + + template <typename TRepeatedField, typename TValue> + inline void + AddValue(TRepeatedField* field, TValue value) { + field->Add(value); + } + + inline void + AddValue(google::protobuf::RepeatedPtrField<TString>* field, const TString& value) { + *(field->Add()) = value; + } + + inline void + FillRepeatedProto(TFlatRepeated* proto, + const THashSet<TString>& skippedFields = THashSet<TString>()) { +#define DEFINE_REPEATED_FIELD(name, type, ...) \ + if (skippedFields.find(#name) == skippedFields.end()) { \ + type values[] = {__VA_ARGS__}; \ + for (size_t i = 0, end = Y_ARRAY_SIZE(values); i < end; ++i) { \ + AddValue(proto->Mutable##name(), values[i]); \ + } \ } #include <library/cpp/protobuf/json/ut/repeated_fields.incl> #undef DEFINE_REPEATED_FIELD - } - - template <typename TProto> - inline void - FillCompositeProto(TProto* proto, const THashSet<TString>& skippedFields = THashSet<TString>()) { - FillFlatProto(proto->MutablePart(), skippedFields); - } - -#define UNIT_ASSERT_PROTOS_EQUAL(lhs, rhs) \ - do { \ - if (lhs.SerializeAsString() != rhs.SerializeAsString()) { \ - Cerr << ">>>>>>>>>> lhs != rhs:" << Endl; \ - Cerr << lhs.DebugString() << Endl; \ - Cerr << rhs.DebugString() << Endl; \ - UNIT_ASSERT_STRINGS_EQUAL(lhs.DebugString(), rhs.DebugString()); \ + } + + template <typename TProto> + inline void + FillCompositeProto(TProto* proto, const THashSet<TString>& skippedFields = THashSet<TString>()) { + FillFlatProto(proto->MutablePart(), skippedFields); + } + +#define UNIT_ASSERT_PROTOS_EQUAL(lhs, rhs) \ + do { \ + if (lhs.SerializeAsString() != rhs.SerializeAsString()) { \ + Cerr << ">>>>>>>>>> lhs != rhs:" << Endl; \ + Cerr << lhs.DebugString() << Endl; \ + Cerr << rhs.DebugString() << Endl; \ + UNIT_ASSERT_STRINGS_EQUAL(lhs.DebugString(), rhs.DebugString()); \ UNIT_ASSERT_STRINGS_EQUAL(lhs.SerializeAsString(), rhs.SerializeAsString()); \ - } \ + } \ } while (false); -} +} diff --git a/library/cpp/protobuf/json/ut/proto2json_ut.cpp b/library/cpp/protobuf/json/ut/proto2json_ut.cpp index 07e52d7f2f..124ac163cd 100644 --- a/library/cpp/protobuf/json/ut/proto2json_ut.cpp +++ b/library/cpp/protobuf/json/ut/proto2json_ut.cpp @@ -33,43 +33,43 @@ Y_UNIT_TEST_SUITE(TProto2JsonFlatTest) { TProto2JsonConfig cfg; cfg.SetMissingSingleKeyMode(TProto2JsonConfig::MissingKeyDefault); UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, cfg)); -#define DEFINE_FIELD(name, value) \ - { \ - auto descr = proto.GetMetadata().descriptor->FindFieldByName(#name); \ - UNIT_ASSERT(descr); \ - UNIT_ASSERT(json.Has(#name)); \ - switch (descr->cpp_type()) { \ - case FieldDescriptor::CPPTYPE_INT32: \ - UNIT_ASSERT(descr->default_value_int32() == json[#name].GetIntegerRobust()); \ - break; \ - case FieldDescriptor::CPPTYPE_INT64: \ - UNIT_ASSERT(descr->default_value_int64() == json[#name].GetIntegerRobust()); \ - break; \ - case FieldDescriptor::CPPTYPE_UINT32: \ - UNIT_ASSERT(descr->default_value_uint32() == json[#name].GetUIntegerRobust()); \ - break; \ - case FieldDescriptor::CPPTYPE_UINT64: \ - UNIT_ASSERT(descr->default_value_uint32() == json[#name].GetUIntegerRobust()); \ - break; \ - case FieldDescriptor::CPPTYPE_DOUBLE: \ - UNIT_ASSERT(descr->default_value_double() == json[#name].GetDoubleRobust()); \ - break; \ - case FieldDescriptor::CPPTYPE_FLOAT: \ - UNIT_ASSERT(descr->default_value_float() == json[#name].GetDoubleRobust()); \ - break; \ - case FieldDescriptor::CPPTYPE_BOOL: \ - UNIT_ASSERT(descr->default_value_bool() == json[#name].GetBooleanRobust()); \ - break; \ - case FieldDescriptor::CPPTYPE_ENUM: \ - UNIT_ASSERT(descr->default_value_enum()->number() == json[#name].GetIntegerRobust()); \ - break; \ - case FieldDescriptor::CPPTYPE_STRING: \ - UNIT_ASSERT(descr->default_value_string() == json[#name].GetStringRobust()); \ - break; \ - default: \ - break; \ - } \ - } +#define DEFINE_FIELD(name, value) \ + { \ + auto descr = proto.GetMetadata().descriptor->FindFieldByName(#name); \ + UNIT_ASSERT(descr); \ + UNIT_ASSERT(json.Has(#name)); \ + switch (descr->cpp_type()) { \ + case FieldDescriptor::CPPTYPE_INT32: \ + UNIT_ASSERT(descr->default_value_int32() == json[#name].GetIntegerRobust()); \ + break; \ + case FieldDescriptor::CPPTYPE_INT64: \ + UNIT_ASSERT(descr->default_value_int64() == json[#name].GetIntegerRobust()); \ + break; \ + case FieldDescriptor::CPPTYPE_UINT32: \ + UNIT_ASSERT(descr->default_value_uint32() == json[#name].GetUIntegerRobust()); \ + break; \ + case FieldDescriptor::CPPTYPE_UINT64: \ + UNIT_ASSERT(descr->default_value_uint32() == json[#name].GetUIntegerRobust()); \ + break; \ + case FieldDescriptor::CPPTYPE_DOUBLE: \ + UNIT_ASSERT(descr->default_value_double() == json[#name].GetDoubleRobust()); \ + break; \ + case FieldDescriptor::CPPTYPE_FLOAT: \ + UNIT_ASSERT(descr->default_value_float() == json[#name].GetDoubleRobust()); \ + break; \ + case FieldDescriptor::CPPTYPE_BOOL: \ + UNIT_ASSERT(descr->default_value_bool() == json[#name].GetBooleanRobust()); \ + break; \ + case FieldDescriptor::CPPTYPE_ENUM: \ + UNIT_ASSERT(descr->default_value_enum()->number() == json[#name].GetIntegerRobust()); \ + break; \ + case FieldDescriptor::CPPTYPE_STRING: \ + UNIT_ASSERT(descr->default_value_string() == json[#name].GetStringRobust()); \ + break; \ + default: \ + break; \ + } \ + } #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD } @@ -79,7 +79,7 @@ Y_UNIT_TEST_SUITE(TProto2JsonFlatTest) { proto.SetField(42); TProto2JsonConfig cfg; - cfg.SetNameGenerator([](const NProtoBuf::FieldDescriptor&) { return "42"; }); + cfg.SetNameGenerator([](const NProtoBuf::FieldDescriptor&) { return "42"; }); TStringStream str; Proto2Json(proto, str, cfg); @@ -92,7 +92,7 @@ Y_UNIT_TEST_SUITE(TProto2JsonFlatTest) { proto.SetEnum(TEnumValueGeneratorType::ENUM_42); TProto2JsonConfig cfg; - cfg.SetEnumValueGenerator([](const NProtoBuf::EnumValueDescriptor&) { return "42"; }); + cfg.SetEnumValueGenerator([](const NProtoBuf::EnumValueDescriptor&) { return "42"; }); TStringStream str; Proto2Json(proto, str, cfg); @@ -101,370 +101,370 @@ Y_UNIT_TEST_SUITE(TProto2JsonFlatTest) { } Y_UNIT_TEST(TestFlatOptional){ - {TFlatOptional proto; - FillFlatProto(&proto); - const NJson::TJsonValue& modelJson = CreateFlatJson(); - { - NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } - - { - TStringStream jsonStream; - NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); - UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } // streamed -} - - // Try to skip each field -#define DEFINE_FIELD(name, value) \ - { \ - THashSet<TString> skippedField; \ - skippedField.insert(#name); \ - TFlatOptional proto; \ - FillFlatProto(&proto, skippedField); \ - const NJson::TJsonValue& modelJson = CreateFlatJson(skippedField); \ - NJson::TJsonValue json; \ - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); \ - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ - { \ - TStringStream jsonStream; \ - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); \ - UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); \ - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ - } \ - } + {TFlatOptional proto; + FillFlatProto(&proto); + const NJson::TJsonValue& modelJson = CreateFlatJson(); + { + NJson::TJsonValue json; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } + + { + TStringStream jsonStream; + NJson::TJsonValue json; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); + UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } // streamed +} + + // Try to skip each field +#define DEFINE_FIELD(name, value) \ + { \ + THashSet<TString> skippedField; \ + skippedField.insert(#name); \ + TFlatOptional proto; \ + FillFlatProto(&proto, skippedField); \ + const NJson::TJsonValue& modelJson = CreateFlatJson(skippedField); \ + NJson::TJsonValue json; \ + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); \ + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ + { \ + TStringStream jsonStream; \ + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); \ + UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); \ + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ + } \ + } #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD -} // TestFlatOptional +} // TestFlatOptional Y_UNIT_TEST(TestFlatRequired){ - {TFlatRequired proto; -FillFlatProto(&proto); -const NJson::TJsonValue& modelJson = CreateFlatJson(); -{ - NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); -} - -{ - TStringStream jsonStream; - NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); - UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); -} // streamed -} - -// Try to skip each field -#define DEFINE_FIELD(name, value) \ - { \ - THashSet<TString> skippedField; \ - skippedField.insert(#name); \ - TFlatRequired proto; \ - FillFlatProto(&proto, skippedField); \ - const NJson::TJsonValue& modelJson = CreateFlatJson(skippedField); \ - NJson::TJsonValue json; \ - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); \ - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ - { \ - TStringStream jsonStream; \ - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); \ - UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); \ - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ - } \ - } + {TFlatRequired proto; +FillFlatProto(&proto); +const NJson::TJsonValue& modelJson = CreateFlatJson(); +{ + NJson::TJsonValue json; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); +} + +{ + TStringStream jsonStream; + NJson::TJsonValue json; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); + UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); +} // streamed +} + +// Try to skip each field +#define DEFINE_FIELD(name, value) \ + { \ + THashSet<TString> skippedField; \ + skippedField.insert(#name); \ + TFlatRequired proto; \ + FillFlatProto(&proto, skippedField); \ + const NJson::TJsonValue& modelJson = CreateFlatJson(skippedField); \ + NJson::TJsonValue json; \ + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); \ + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ + { \ + TStringStream jsonStream; \ + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); \ + UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); \ + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ + } \ + } #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD -} // TestFlatRequired +} // TestFlatRequired Y_UNIT_TEST(TestFlatRepeated) { - { - TFlatRepeated proto; - FillRepeatedProto(&proto); - const NJson::TJsonValue& modelJson = CreateRepeatedFlatJson(); + { + TFlatRepeated proto; + FillRepeatedProto(&proto); + const NJson::TJsonValue& modelJson = CreateRepeatedFlatJson(); { - NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + NJson::TJsonValue json; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); } - { - TStringStream jsonStream; - NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); - UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } // streamed - } - - TProto2JsonConfig config; - config.SetMissingRepeatedKeyMode(TProto2JsonConfig::MissingKeySkip); - - // Try to skip each field -#define DEFINE_REPEATED_FIELD(name, ...) \ - { \ - THashSet<TString> skippedField; \ - skippedField.insert(#name); \ - TFlatRepeated proto; \ - FillRepeatedProto(&proto, skippedField); \ - const NJson::TJsonValue& modelJson = CreateRepeatedFlatJson(skippedField); \ - NJson::TJsonValue json; \ - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); \ - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ - { \ - TStringStream jsonStream; \ - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream, config)); \ - UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); \ - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ - } \ - } + { + TStringStream jsonStream; + NJson::TJsonValue json; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); + UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } // streamed + } + + TProto2JsonConfig config; + config.SetMissingRepeatedKeyMode(TProto2JsonConfig::MissingKeySkip); + + // Try to skip each field +#define DEFINE_REPEATED_FIELD(name, ...) \ + { \ + THashSet<TString> skippedField; \ + skippedField.insert(#name); \ + TFlatRepeated proto; \ + FillRepeatedProto(&proto, skippedField); \ + const NJson::TJsonValue& modelJson = CreateRepeatedFlatJson(skippedField); \ + NJson::TJsonValue json; \ + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); \ + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ + { \ + TStringStream jsonStream; \ + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream, config)); \ + UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); \ + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ + } \ + } #include <library/cpp/protobuf/json/ut/repeated_fields.incl> #undef DEFINE_REPEATED_FIELD -} // TestFlatRepeated +} // TestFlatRepeated Y_UNIT_TEST(TestCompositeOptional){ - {TCompositeOptional proto; -FillCompositeProto(&proto); -const NJson::TJsonValue& modelJson = CreateCompositeJson(); -{ - NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); -} - -{ - TStringStream jsonStream; - NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); - UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); -} // streamed -} - -// Try to skip each field -#define DEFINE_FIELD(name, value) \ - { \ - THashSet<TString> skippedField; \ - skippedField.insert(#name); \ - TCompositeOptional proto; \ - FillCompositeProto(&proto, skippedField); \ - const NJson::TJsonValue& modelJson = CreateCompositeJson(skippedField); \ - NJson::TJsonValue json; \ - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); \ - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ - { \ - TStringStream jsonStream; \ - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); \ - UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); \ - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ - } \ - } + {TCompositeOptional proto; +FillCompositeProto(&proto); +const NJson::TJsonValue& modelJson = CreateCompositeJson(); +{ + NJson::TJsonValue json; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); +} + +{ + TStringStream jsonStream; + NJson::TJsonValue json; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); + UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); +} // streamed +} + +// Try to skip each field +#define DEFINE_FIELD(name, value) \ + { \ + THashSet<TString> skippedField; \ + skippedField.insert(#name); \ + TCompositeOptional proto; \ + FillCompositeProto(&proto, skippedField); \ + const NJson::TJsonValue& modelJson = CreateCompositeJson(skippedField); \ + NJson::TJsonValue json; \ + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); \ + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ + { \ + TStringStream jsonStream; \ + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); \ + UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); \ + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ + } \ + } #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD -} // TestCompositeOptional +} // TestCompositeOptional Y_UNIT_TEST(TestCompositeRequired){ - {TCompositeRequired proto; -FillCompositeProto(&proto); -const NJson::TJsonValue& modelJson = CreateCompositeJson(); -{ - NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); -} - -{ - TStringStream jsonStream; - NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); - UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); -} // streamed -} - -// Try to skip each field -#define DEFINE_FIELD(name, value) \ - { \ - THashSet<TString> skippedField; \ - skippedField.insert(#name); \ - TCompositeRequired proto; \ - FillCompositeProto(&proto, skippedField); \ - const NJson::TJsonValue& modelJson = CreateCompositeJson(skippedField); \ - NJson::TJsonValue json; \ - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); \ - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ - { \ - TStringStream jsonStream; \ - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); \ - UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); \ - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ - } \ - } + {TCompositeRequired proto; +FillCompositeProto(&proto); +const NJson::TJsonValue& modelJson = CreateCompositeJson(); +{ + NJson::TJsonValue json; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); +} + +{ + TStringStream jsonStream; + NJson::TJsonValue json; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); + UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); +} // streamed +} + +// Try to skip each field +#define DEFINE_FIELD(name, value) \ + { \ + THashSet<TString> skippedField; \ + skippedField.insert(#name); \ + TCompositeRequired proto; \ + FillCompositeProto(&proto, skippedField); \ + const NJson::TJsonValue& modelJson = CreateCompositeJson(skippedField); \ + NJson::TJsonValue json; \ + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); \ + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ + { \ + TStringStream jsonStream; \ + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); \ + UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); \ + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); \ + } \ + } #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD -} // TestCompositeRequired +} // TestCompositeRequired Y_UNIT_TEST(TestCompositeRepeated) { - { - TFlatOptional partProto; - FillFlatProto(&partProto); - TCompositeRepeated proto; - proto.AddPart()->CopyFrom(partProto); - - NJson::TJsonValue modelJson; - NJson::TJsonValue modelArray; - modelArray.AppendValue(CreateFlatJson()); - modelJson.InsertValue("Part", modelArray); + { + TFlatOptional partProto; + FillFlatProto(&partProto); + TCompositeRepeated proto; + proto.AddPart()->CopyFrom(partProto); + + NJson::TJsonValue modelJson; + NJson::TJsonValue modelArray; + modelArray.AppendValue(CreateFlatJson()); + modelJson.InsertValue("Part", modelArray); { - NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + NJson::TJsonValue json; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); } { - TStringStream jsonStream; - NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); - UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } // streamed - } - - { - // Array of messages with each field skipped - TCompositeRepeated proto; - NJson::TJsonValue modelArray; - -#define DEFINE_REPEATED_FIELD(name, ...) \ - { \ - THashSet<TString> skippedField; \ - skippedField.insert(#name); \ - TFlatOptional partProto; \ - FillFlatProto(&partProto, skippedField); \ - proto.AddPart()->CopyFrom(partProto); \ - modelArray.AppendValue(CreateFlatJson(skippedField)); \ - } + TStringStream jsonStream; + NJson::TJsonValue json; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); + UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } // streamed + } + + { + // Array of messages with each field skipped + TCompositeRepeated proto; + NJson::TJsonValue modelArray; + +#define DEFINE_REPEATED_FIELD(name, ...) \ + { \ + THashSet<TString> skippedField; \ + skippedField.insert(#name); \ + TFlatOptional partProto; \ + FillFlatProto(&partProto, skippedField); \ + proto.AddPart()->CopyFrom(partProto); \ + modelArray.AppendValue(CreateFlatJson(skippedField)); \ + } #include <library/cpp/protobuf/json/ut/repeated_fields.incl> #undef DEFINE_REPEATED_FIELD - NJson::TJsonValue modelJson; - modelJson.InsertValue("Part", modelArray); + NJson::TJsonValue modelJson; + modelJson.InsertValue("Part", modelArray); { NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); UNIT_ASSERT_JSONS_EQUAL(json, modelJson); } { - TStringStream jsonStream; + TStringStream jsonStream; NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); - UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStream)); + UNIT_ASSERT(ReadJsonTree(&jsonStream, &json)); UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } // streamed - } -} // TestCompositeRepeated + } // streamed + } +} // TestCompositeRepeated Y_UNIT_TEST(TestEnumConfig) { - { - TFlatOptional proto; - proto.SetEnum(E_1); - NJson::TJsonValue modelJson; - modelJson.InsertValue("Enum", 1); - NJson::TJsonValue json; - TProto2JsonConfig config; - config.EnumMode = TProto2JsonConfig::EnumNumber; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } - - { - TFlatOptional proto; - proto.SetEnum(E_1); - NJson::TJsonValue modelJson; - modelJson.InsertValue("Enum", "E_1"); - NJson::TJsonValue json; - TProto2JsonConfig config; - config.EnumMode = TProto2JsonConfig::EnumName; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } - - { - TFlatOptional proto; - proto.SetEnum(E_1); - NJson::TJsonValue modelJson; - modelJson.InsertValue("Enum", "NProtobufJsonTest.E_1"); - NJson::TJsonValue json; - TProto2JsonConfig config; - config.EnumMode = TProto2JsonConfig::EnumFullName; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } - - { - TFlatOptional proto; - proto.SetEnum(E_1); - NJson::TJsonValue modelJson; - modelJson.InsertValue("Enum", "e_1"); - NJson::TJsonValue json; - TProto2JsonConfig config; - config.EnumMode = TProto2JsonConfig::EnumNameLowerCase; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } - - { - TFlatOptional proto; - proto.SetEnum(E_1); - NJson::TJsonValue modelJson; - modelJson.InsertValue("Enum", "nprotobufjsontest.e_1"); - NJson::TJsonValue json; - TProto2JsonConfig config; - config.EnumMode = TProto2JsonConfig::EnumFullNameLowerCase; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } -} // TestEnumConfig - + { + TFlatOptional proto; + proto.SetEnum(E_1); + NJson::TJsonValue modelJson; + modelJson.InsertValue("Enum", 1); + NJson::TJsonValue json; + TProto2JsonConfig config; + config.EnumMode = TProto2JsonConfig::EnumNumber; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } + + { + TFlatOptional proto; + proto.SetEnum(E_1); + NJson::TJsonValue modelJson; + modelJson.InsertValue("Enum", "E_1"); + NJson::TJsonValue json; + TProto2JsonConfig config; + config.EnumMode = TProto2JsonConfig::EnumName; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } + + { + TFlatOptional proto; + proto.SetEnum(E_1); + NJson::TJsonValue modelJson; + modelJson.InsertValue("Enum", "NProtobufJsonTest.E_1"); + NJson::TJsonValue json; + TProto2JsonConfig config; + config.EnumMode = TProto2JsonConfig::EnumFullName; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } + + { + TFlatOptional proto; + proto.SetEnum(E_1); + NJson::TJsonValue modelJson; + modelJson.InsertValue("Enum", "e_1"); + NJson::TJsonValue json; + TProto2JsonConfig config; + config.EnumMode = TProto2JsonConfig::EnumNameLowerCase; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } + + { + TFlatOptional proto; + proto.SetEnum(E_1); + NJson::TJsonValue modelJson; + modelJson.InsertValue("Enum", "nprotobufjsontest.e_1"); + NJson::TJsonValue json; + TProto2JsonConfig config; + config.EnumMode = TProto2JsonConfig::EnumFullNameLowerCase; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } +} // TestEnumConfig + Y_UNIT_TEST(TestMissingSingleKeyConfig) { - { - TFlatOptional proto; - NJson::TJsonValue modelJson(NJson::JSON_MAP); - NJson::TJsonValue json; - TProto2JsonConfig config; - config.MissingSingleKeyMode = TProto2JsonConfig::MissingKeySkip; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } - - { - NJson::TJsonValue modelJson; -#define DEFINE_FIELD(name, value) \ - modelJson.InsertValue(#name, NJson::TJsonValue(NJson::JSON_NULL)); + { + TFlatOptional proto; + NJson::TJsonValue modelJson(NJson::JSON_MAP); + NJson::TJsonValue json; + TProto2JsonConfig config; + config.MissingSingleKeyMode = TProto2JsonConfig::MissingKeySkip; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } + + { + NJson::TJsonValue modelJson; +#define DEFINE_FIELD(name, value) \ + modelJson.InsertValue(#name, NJson::TJsonValue(NJson::JSON_NULL)); #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD - TFlatOptional proto; - NJson::TJsonValue json; - TProto2JsonConfig config; - config.MissingSingleKeyMode = TProto2JsonConfig::MissingKeyNull; + TFlatOptional proto; + NJson::TJsonValue json; + TProto2JsonConfig config; + config.MissingSingleKeyMode = TProto2JsonConfig::MissingKeyNull; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } { // Test MissingKeyExplicitDefaultThrowRequired for non explicit default values. TFlatOptional proto; @@ -511,46 +511,46 @@ Y_UNIT_TEST(TestMissingSingleKeyConfig) { UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); UNIT_ASSERT_JSONS_EQUAL(json, modelJson); } -} // TestMissingSingleKeyConfig +} // TestMissingSingleKeyConfig Y_UNIT_TEST(TestMissingRepeatedKeyNoConfig) { - { - TFlatRepeated proto; - NJson::TJsonValue modelJson(NJson::JSON_MAP); - NJson::TJsonValue json; + { + TFlatRepeated proto; + NJson::TJsonValue modelJson(NJson::JSON_MAP); + NJson::TJsonValue json; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } -} // TestMissingRepeatedKeyNoConfig + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } +} // TestMissingRepeatedKeyNoConfig Y_UNIT_TEST(TestMissingRepeatedKeyConfig) { - { - TFlatRepeated proto; - NJson::TJsonValue modelJson(NJson::JSON_MAP); - NJson::TJsonValue json; - TProto2JsonConfig config; - config.MissingRepeatedKeyMode = TProto2JsonConfig::MissingKeySkip; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } - - { - NJson::TJsonValue modelJson; -#define DEFINE_FIELD(name, value) \ - modelJson.InsertValue(#name, NJson::TJsonValue(NJson::JSON_NULL)); + { + TFlatRepeated proto; + NJson::TJsonValue modelJson(NJson::JSON_MAP); + NJson::TJsonValue json; + TProto2JsonConfig config; + config.MissingRepeatedKeyMode = TProto2JsonConfig::MissingKeySkip; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } + + { + NJson::TJsonValue modelJson; +#define DEFINE_FIELD(name, value) \ + modelJson.InsertValue(#name, NJson::TJsonValue(NJson::JSON_NULL)); #include <library/cpp/protobuf/json/ut/fields.incl> #undef DEFINE_FIELD - TFlatRepeated proto; - NJson::TJsonValue json; - TProto2JsonConfig config; - config.MissingRepeatedKeyMode = TProto2JsonConfig::MissingKeyNull; + TFlatRepeated proto; + NJson::TJsonValue json; + TProto2JsonConfig config; + config.MissingRepeatedKeyMode = TProto2JsonConfig::MissingKeyNull; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); - UNIT_ASSERT_JSONS_EQUAL(json, modelJson); - } + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); + UNIT_ASSERT_JSONS_EQUAL(json, modelJson); + } { TFlatRepeated proto; NJson::TJsonValue modelJson(NJson::JSON_MAP); @@ -562,199 +562,199 @@ Y_UNIT_TEST(TestMissingRepeatedKeyConfig) { UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, json, config)); UNIT_ASSERT_JSONS_EQUAL(json, modelJson); } -} // TestMissingRepeatedKeyConfig +} // TestMissingRepeatedKeyConfig Y_UNIT_TEST(TestEscaping) { - // No escape - { - TString modelStr(R"_({"String":"value\""})_"); - - TFlatOptional proto; - proto.SetString(R"_(value")_"); - TStringStream jsonStr; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } - - // TEscapeJTransform - { - TString modelStr(R"_({"String":"value\""})_"); - - TFlatOptional proto; - proto.SetString(R"_(value")_"); - TProto2JsonConfig config; - config.StringTransforms.push_back(new TEscapeJTransform<false, true>()); - TStringStream jsonStr; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(modelStr, jsonStr.Str()); - } - - // TCEscapeTransform - { - TString modelStr(R"_({"String":"value\""})_"); - - TFlatOptional proto; - proto.SetString(R"_(value")_"); - TProto2JsonConfig config; - config.StringTransforms.push_back(new TCEscapeTransform()); - TStringStream jsonStr; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } - - // TSafeUtf8CEscapeTransform - { - TString modelStr(R"_({"String":"value\""})_"); - - TFlatOptional proto; - proto.SetString(R"_(value")_"); - TProto2JsonConfig config; - config.StringTransforms.push_back(new TSafeUtf8CEscapeTransform()); - TStringStream jsonStr; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } -} // TestEscaping - -class TBytesTransform: public IStringTransform { -public: - int GetType() const override { - return 0; - } - void Transform(TString&) const override { - } - void TransformBytes(TString& str) const override { - str = "bytes"; - } -}; + // No escape + { + TString modelStr(R"_({"String":"value\""})_"); + + TFlatOptional proto; + proto.SetString(R"_(value")_"); + TStringStream jsonStr; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } + + // TEscapeJTransform + { + TString modelStr(R"_({"String":"value\""})_"); + + TFlatOptional proto; + proto.SetString(R"_(value")_"); + TProto2JsonConfig config; + config.StringTransforms.push_back(new TEscapeJTransform<false, true>()); + TStringStream jsonStr; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(modelStr, jsonStr.Str()); + } + + // TCEscapeTransform + { + TString modelStr(R"_({"String":"value\""})_"); + + TFlatOptional proto; + proto.SetString(R"_(value")_"); + TProto2JsonConfig config; + config.StringTransforms.push_back(new TCEscapeTransform()); + TStringStream jsonStr; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } + + // TSafeUtf8CEscapeTransform + { + TString modelStr(R"_({"String":"value\""})_"); + + TFlatOptional proto; + proto.SetString(R"_(value")_"); + TProto2JsonConfig config; + config.StringTransforms.push_back(new TSafeUtf8CEscapeTransform()); + TStringStream jsonStr; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } +} // TestEscaping + +class TBytesTransform: public IStringTransform { +public: + int GetType() const override { + return 0; + } + void Transform(TString&) const override { + } + void TransformBytes(TString& str) const override { + str = "bytes"; + } +}; Y_UNIT_TEST(TestBytesTransform) { - // Test that string field is not changed - { - TString modelStr(R"_({"String":"value"})_"); + // Test that string field is not changed + { + TString modelStr(R"_({"String":"value"})_"); - TFlatOptional proto; - proto.SetString(R"_(value)_"); - TProto2JsonConfig config; - config.StringTransforms.push_back(new TBytesTransform()); - TStringStream jsonStr; + TFlatOptional proto; + proto.SetString(R"_(value)_"); + TProto2JsonConfig config; + config.StringTransforms.push_back(new TBytesTransform()); + TStringStream jsonStr; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } - // Test that bytes field is changed - { - TString modelStr(R"_({"Bytes":"bytes"})_"); + // Test that bytes field is changed + { + TString modelStr(R"_({"Bytes":"bytes"})_"); - TFlatOptional proto; - proto.SetBytes(R"_(value)_"); - TProto2JsonConfig config; - config.StringTransforms.push_back(new TBytesTransform()); - TStringStream jsonStr; + TFlatOptional proto; + proto.SetBytes(R"_(value)_"); + TProto2JsonConfig config; + config.StringTransforms.push_back(new TBytesTransform()); + TStringStream jsonStr; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); } -} +} Y_UNIT_TEST(TestFieldNameMode) { - // Original case 1 - { - TString modelStr(R"_({"String":"value"})_"); - - TFlatOptional proto; - proto.SetString("value"); - TStringStream jsonStr; - TProto2JsonConfig config; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } - - // Original case 2 - { - TString modelStr(R"_({"String":"value"})_"); - - TFlatOptional proto; - proto.SetString("value"); - TStringStream jsonStr; - TProto2JsonConfig config; - config.FieldNameMode = TProto2JsonConfig::FieldNameOriginalCase; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } - - // Lowercase - { - TString modelStr(R"_({"string":"value"})_"); - - TFlatOptional proto; - proto.SetString("value"); - TStringStream jsonStr; - TProto2JsonConfig config; - config.FieldNameMode = TProto2JsonConfig::FieldNameLowerCase; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } - - // Uppercase - { - TString modelStr(R"_({"STRING":"value"})_"); - - TFlatOptional proto; - proto.SetString("value"); - TStringStream jsonStr; - TProto2JsonConfig config; - config.FieldNameMode = TProto2JsonConfig::FieldNameUpperCase; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } - - // Camelcase - { - TString modelStr(R"_({"string":"value"})_"); - - TFlatOptional proto; - proto.SetString("value"); - TStringStream jsonStr; - TProto2JsonConfig config; - config.FieldNameMode = TProto2JsonConfig::FieldNameCamelCase; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } - { - TString modelStr(R"_({"oneString":"value"})_"); - - TFlatOptional proto; - proto.SetOneString("value"); - TStringStream jsonStr; - TProto2JsonConfig config; - config.FieldNameMode = TProto2JsonConfig::FieldNameCamelCase; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } - { - TString modelStr(R"_({"oneTwoString":"value"})_"); - - TFlatOptional proto; - proto.SetOneTwoString("value"); - TStringStream jsonStr; - TProto2JsonConfig config; - config.FieldNameMode = TProto2JsonConfig::FieldNameCamelCase; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } + // Original case 1 + { + TString modelStr(R"_({"String":"value"})_"); + + TFlatOptional proto; + proto.SetString("value"); + TStringStream jsonStr; + TProto2JsonConfig config; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } + + // Original case 2 + { + TString modelStr(R"_({"String":"value"})_"); + + TFlatOptional proto; + proto.SetString("value"); + TStringStream jsonStr; + TProto2JsonConfig config; + config.FieldNameMode = TProto2JsonConfig::FieldNameOriginalCase; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } + + // Lowercase + { + TString modelStr(R"_({"string":"value"})_"); + + TFlatOptional proto; + proto.SetString("value"); + TStringStream jsonStr; + TProto2JsonConfig config; + config.FieldNameMode = TProto2JsonConfig::FieldNameLowerCase; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } + + // Uppercase + { + TString modelStr(R"_({"STRING":"value"})_"); + + TFlatOptional proto; + proto.SetString("value"); + TStringStream jsonStr; + TProto2JsonConfig config; + config.FieldNameMode = TProto2JsonConfig::FieldNameUpperCase; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } + + // Camelcase + { + TString modelStr(R"_({"string":"value"})_"); + + TFlatOptional proto; + proto.SetString("value"); + TStringStream jsonStr; + TProto2JsonConfig config; + config.FieldNameMode = TProto2JsonConfig::FieldNameCamelCase; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } + { + TString modelStr(R"_({"oneString":"value"})_"); + + TFlatOptional proto; + proto.SetOneString("value"); + TStringStream jsonStr; + TProto2JsonConfig config; + config.FieldNameMode = TProto2JsonConfig::FieldNameCamelCase; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } + { + TString modelStr(R"_({"oneTwoString":"value"})_"); + + TFlatOptional proto; + proto.SetOneTwoString("value"); + TStringStream jsonStr; + TProto2JsonConfig config; + config.FieldNameMode = TProto2JsonConfig::FieldNameCamelCase; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } // snake_case { @@ -822,189 +822,189 @@ Y_UNIT_TEST(TestFieldNameMode) { UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); } - // Original case, repeated - { - TString modelStr(R"_({"I32":[1,2]})_"); - - TFlatRepeated proto; - proto.AddI32(1); - proto.AddI32(2); - TStringStream jsonStr; - TProto2JsonConfig config; - config.FieldNameMode = TProto2JsonConfig::FieldNameOriginalCase; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } - - // Lower case, repeated - { - TString modelStr(R"_({"i32":[1,2]})_"); - - TFlatRepeated proto; - proto.AddI32(1); - proto.AddI32(2); - TStringStream jsonStr; - TProto2JsonConfig config; - config.FieldNameMode = TProto2JsonConfig::FieldNameLowerCase; - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } - - // UseJsonName - { - // FIXME(CONTRIB-139): see the comment about UseJsonName in json2proto_ut.cpp: - // Def_upper json name should be "DefUpper". - TString modelStr(R"_({"My-Upper":1,"my-lower":2,"defUpper":3,"defLower":4})_"); - - TWithJsonName proto; - proto.Setmy_upper(1); - proto.SetMy_lower(2); - proto.SetDef_upper(3); - proto.Setdef_lower(4); - TStringStream jsonStr; - TProto2JsonConfig config; - config.SetUseJsonName(true); - - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_STRINGS_EQUAL(jsonStr.Str(), modelStr); - } - - // FieldNameMode with UseJsonName - { - TProto2JsonConfig config; - config.SetFieldNameMode(TProto2JsonConfig::FieldNameLowerCase); - UNIT_ASSERT_EXCEPTION_CONTAINS( - config.SetUseJsonName(true), yexception, "mutually exclusive"); - } - { - TProto2JsonConfig config; - config.SetUseJsonName(true); - UNIT_ASSERT_EXCEPTION_CONTAINS( - config.SetFieldNameMode(TProto2JsonConfig::FieldNameLowerCase), yexception, "mutually exclusive"); - } - - /// TODO: test missing keys -} // TestFieldNameMode + // Original case, repeated + { + TString modelStr(R"_({"I32":[1,2]})_"); + + TFlatRepeated proto; + proto.AddI32(1); + proto.AddI32(2); + TStringStream jsonStr; + TProto2JsonConfig config; + config.FieldNameMode = TProto2JsonConfig::FieldNameOriginalCase; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } + + // Lower case, repeated + { + TString modelStr(R"_({"i32":[1,2]})_"); + + TFlatRepeated proto; + proto.AddI32(1); + proto.AddI32(2); + TStringStream jsonStr; + TProto2JsonConfig config; + config.FieldNameMode = TProto2JsonConfig::FieldNameLowerCase; + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } + + // UseJsonName + { + // FIXME(CONTRIB-139): see the comment about UseJsonName in json2proto_ut.cpp: + // Def_upper json name should be "DefUpper". + TString modelStr(R"_({"My-Upper":1,"my-lower":2,"defUpper":3,"defLower":4})_"); + + TWithJsonName proto; + proto.Setmy_upper(1); + proto.SetMy_lower(2); + proto.SetDef_upper(3); + proto.Setdef_lower(4); + TStringStream jsonStr; + TProto2JsonConfig config; + config.SetUseJsonName(true); + + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + UNIT_ASSERT_STRINGS_EQUAL(jsonStr.Str(), modelStr); + } + + // FieldNameMode with UseJsonName + { + TProto2JsonConfig config; + config.SetFieldNameMode(TProto2JsonConfig::FieldNameLowerCase); + UNIT_ASSERT_EXCEPTION_CONTAINS( + config.SetUseJsonName(true), yexception, "mutually exclusive"); + } + { + TProto2JsonConfig config; + config.SetUseJsonName(true); + UNIT_ASSERT_EXCEPTION_CONTAINS( + config.SetFieldNameMode(TProto2JsonConfig::FieldNameLowerCase), yexception, "mutually exclusive"); + } + + /// TODO: test missing keys +} // TestFieldNameMode Y_UNIT_TEST(TestNan) { - TFlatOptional proto; - proto.SetDouble(std::numeric_limits<double>::quiet_NaN()); + TFlatOptional proto; + proto.SetDouble(std::numeric_limits<double>::quiet_NaN()); - UNIT_ASSERT_EXCEPTION(Proto2Json(proto, TProto2JsonConfig()), yexception); -} // TestNan + UNIT_ASSERT_EXCEPTION(Proto2Json(proto, TProto2JsonConfig()), yexception); +} // TestNan Y_UNIT_TEST(TestInf) { - TFlatOptional proto; - proto.SetFloat(std::numeric_limits<float>::infinity()); + TFlatOptional proto; + proto.SetFloat(std::numeric_limits<float>::infinity()); - UNIT_ASSERT_EXCEPTION(Proto2Json(proto, TProto2JsonConfig()), yexception); -} // TestInf + UNIT_ASSERT_EXCEPTION(Proto2Json(proto, TProto2JsonConfig()), yexception); +} // TestInf Y_UNIT_TEST(TestMap) { - TMapType proto; - - auto& items = *proto.MutableItems(); - items["key1"] = "value1"; - items["key2"] = "value2"; - items["key3"] = "value3"; - - TString modelStr(R"_({"Items":[{"key":"key3","value":"value3"},{"key":"key2","value":"value2"},{"key":"key1","value":"value1"}]})_"); - - TStringStream jsonStr; - TProto2JsonConfig config; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - - NJson::TJsonValue jsonValue, modelValue; - NJson::TJsonValue::TArray jsonItems, modelItems; - UNIT_ASSERT(NJson::ReadJsonTree(jsonStr.Str(), &jsonValue)); - UNIT_ASSERT(NJson::ReadJsonTree(modelStr, &modelValue)); - UNIT_ASSERT(jsonValue.Has("Items")); - jsonValue["Items"].GetArray(&jsonItems); - modelValue["Items"].GetArray(&modelItems); - auto itemKey = [](const NJson::TJsonValue& v) { - return v["key"].GetString(); - }; - SortBy(jsonItems, itemKey); - SortBy(modelItems, itemKey); - UNIT_ASSERT_EQUAL(jsonItems, modelItems); -} // TestMap + TMapType proto; + + auto& items = *proto.MutableItems(); + items["key1"] = "value1"; + items["key2"] = "value2"; + items["key3"] = "value3"; + + TString modelStr(R"_({"Items":[{"key":"key3","value":"value3"},{"key":"key2","value":"value2"},{"key":"key1","value":"value1"}]})_"); + + TStringStream jsonStr; + TProto2JsonConfig config; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + + NJson::TJsonValue jsonValue, modelValue; + NJson::TJsonValue::TArray jsonItems, modelItems; + UNIT_ASSERT(NJson::ReadJsonTree(jsonStr.Str(), &jsonValue)); + UNIT_ASSERT(NJson::ReadJsonTree(modelStr, &modelValue)); + UNIT_ASSERT(jsonValue.Has("Items")); + jsonValue["Items"].GetArray(&jsonItems); + modelValue["Items"].GetArray(&modelItems); + auto itemKey = [](const NJson::TJsonValue& v) { + return v["key"].GetString(); + }; + SortBy(jsonItems, itemKey); + SortBy(modelItems, itemKey); + UNIT_ASSERT_EQUAL(jsonItems, modelItems); +} // TestMap Y_UNIT_TEST(TestMapAsObject) { - TMapType proto; + TMapType proto; - auto& items = *proto.MutableItems(); - items["key1"] = "value1"; - items["key2"] = "value2"; - items["key3"] = "value3"; + auto& items = *proto.MutableItems(); + items["key1"] = "value1"; + items["key2"] = "value2"; + items["key3"] = "value3"; - TString modelStr(R"_({"Items":{"key3":"value3","key2":"value2","key1":"value1"}})_"); + TString modelStr(R"_({"Items":{"key3":"value3","key2":"value2","key1":"value1"}})_"); - TStringStream jsonStr; - TProto2JsonConfig config; - config.MapAsObject = true; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); + TStringStream jsonStr; + TProto2JsonConfig config; + config.MapAsObject = true; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); -} // TestMapAsObject + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); +} // TestMapAsObject Y_UNIT_TEST(TestMapWTF) { - TMapType proto; + TMapType proto; - auto& items = *proto.MutableItems(); - items["key1"] = "value1"; - items["key2"] = "value2"; - items["key3"] = "value3"; + auto& items = *proto.MutableItems(); + items["key1"] = "value1"; + items["key2"] = "value2"; + items["key3"] = "value3"; - TString modelStr(R"_({"Items":{"key3":"value3","key2":"value2","key1":"value1"}})_"); + TString modelStr(R"_({"Items":{"key3":"value3","key2":"value2","key1":"value1"}})_"); - TStringStream jsonStr; - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr)); + TStringStream jsonStr; + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr)); - UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); -} // TestMapWTF + UNIT_ASSERT_JSON_STRINGS_EQUAL(jsonStr.Str(), modelStr); +} // TestMapWTF Y_UNIT_TEST(TestStringifyLongNumbers) { -#define TEST_SINGLE(flag, value, expectString) \ - do { \ - TFlatOptional proto; \ - proto.SetSI64(value); \ - \ - TStringStream jsonStr; \ - TProto2JsonConfig config; \ - config.SetStringifyLongNumbers(flag); \ - UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); \ - if (expectString) { \ - UNIT_ASSERT_EQUAL(jsonStr.Str(), "{\"SI64\":\"" #value "\"}"); \ - } else { \ - UNIT_ASSERT_EQUAL(jsonStr.Str(), "{\"SI64\":" #value "}"); \ - } \ - } while (false) - - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersNever, 1, false); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersNever, 1000000000, false); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersNever, 10000000000000000, false); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersNever, -1, false); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersNever, -1000000000, false); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersNever, -10000000000000000, false); - - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForDouble, 1, false); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForDouble, 1000000000, false); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForDouble, 10000000000000000, true); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForDouble, -1, false); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForDouble, -1000000000, false); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForDouble, -10000000000000000, true); - - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForFloat, 1, false); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForFloat, 1000000000, true); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForFloat, 10000000000000000, true); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForFloat, -1, false); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForFloat, -1000000000, true); - TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForFloat, -10000000000000000, true); +#define TEST_SINGLE(flag, value, expectString) \ + do { \ + TFlatOptional proto; \ + proto.SetSI64(value); \ + \ + TStringStream jsonStr; \ + TProto2JsonConfig config; \ + config.SetStringifyLongNumbers(flag); \ + UNIT_ASSERT_NO_EXCEPTION(Proto2Json(proto, jsonStr, config)); \ + if (expectString) { \ + UNIT_ASSERT_EQUAL(jsonStr.Str(), "{\"SI64\":\"" #value "\"}"); \ + } else { \ + UNIT_ASSERT_EQUAL(jsonStr.Str(), "{\"SI64\":" #value "}"); \ + } \ + } while (false) + + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersNever, 1, false); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersNever, 1000000000, false); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersNever, 10000000000000000, false); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersNever, -1, false); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersNever, -1000000000, false); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersNever, -10000000000000000, false); + + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForDouble, 1, false); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForDouble, 1000000000, false); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForDouble, 10000000000000000, true); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForDouble, -1, false); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForDouble, -1000000000, false); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForDouble, -10000000000000000, true); + + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForFloat, 1, false); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForFloat, 1000000000, true); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForFloat, 10000000000000000, true); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForFloat, -1, false); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForFloat, -1000000000, true); + TEST_SINGLE(TProto2JsonConfig::StringifyLongNumbersForFloat, -10000000000000000, true); #undef TEST_SINGLE -} // TestStringifyLongNumbers +} // TestStringifyLongNumbers Y_UNIT_TEST(TestExtension) { TExtensionField proto; diff --git a/library/cpp/protobuf/json/ut/string_transform_ut.cpp b/library/cpp/protobuf/json/ut/string_transform_ut.cpp index a31dabcb0f..90debecd66 100644 --- a/library/cpp/protobuf/json/ut/string_transform_ut.cpp +++ b/library/cpp/protobuf/json/ut/string_transform_ut.cpp @@ -40,7 +40,7 @@ Y_UNIT_TEST_SUITE(TDoubleEscapeTransform) { Y_UNIT_TEST_SUITE(TDoubleUnescapeTransform) { Y_UNIT_TEST(TestEmptyString) { - const NProtobufJson::IStringTransform& transform = NProtobufJson::TDoubleUnescapeTransform(); + const NProtobufJson::IStringTransform& transform = NProtobufJson::TDoubleUnescapeTransform(); TString s; s = ""; transform.Transform(s); @@ -48,7 +48,7 @@ Y_UNIT_TEST_SUITE(TDoubleUnescapeTransform) { } Y_UNIT_TEST(TestAlphabeticString) { - const NProtobufJson::IStringTransform& transform = NProtobufJson::TDoubleUnescapeTransform(); + const NProtobufJson::IStringTransform& transform = NProtobufJson::TDoubleUnescapeTransform(); TString s; s = "abacaba"; transform.Transform(s); @@ -57,7 +57,7 @@ Y_UNIT_TEST_SUITE(TDoubleUnescapeTransform) { } Y_UNIT_TEST(TestRussianSymbols) { - const NProtobufJson::IStringTransform& transform = NProtobufJson::TDoubleUnescapeTransform(); + const NProtobufJson::IStringTransform& transform = NProtobufJson::TDoubleUnescapeTransform(); TString s; s = "\\\\321\\\\202\\\\320\\\\265\\\\321\\\\201\\\\321\\\\202"; transform.Transform(s); @@ -65,7 +65,7 @@ Y_UNIT_TEST_SUITE(TDoubleUnescapeTransform) { } Y_UNIT_TEST(TestEscapeSpecialSymbols) { - const NProtobufJson::IStringTransform& transform = NProtobufJson::TDoubleUnescapeTransform(); + const NProtobufJson::IStringTransform& transform = NProtobufJson::TDoubleUnescapeTransform(); TString s; s = "aba\\\\\\\\ca\\\\\\\"ba"; transform.Transform(s); @@ -73,7 +73,7 @@ Y_UNIT_TEST_SUITE(TDoubleUnescapeTransform) { } Y_UNIT_TEST(TestEscapeSpecialSymbolsDifficultCases) { - const NProtobufJson::IStringTransform& transform = NProtobufJson::TDoubleUnescapeTransform(); + const NProtobufJson::IStringTransform& transform = NProtobufJson::TDoubleUnescapeTransform(); TString s; s = "\\\\\\\\\\\\\\\\"; transform.Transform(s); diff --git a/library/cpp/protobuf/util/cast.h b/library/cpp/protobuf/util/cast.h index 83749dfcee..e99d4f200a 100644 --- a/library/cpp/protobuf/util/cast.h +++ b/library/cpp/protobuf/util/cast.h @@ -1,5 +1,5 @@ #pragma once - + #include "traits.h" #include <google/protobuf/descriptor.h> @@ -8,149 +8,149 @@ #include <util/generic/cast.h> namespace NProtoBuf { - // C++ compatible conversions of FieldDescriptor::CppType's - - using ECppType = FieldDescriptor::CppType; + // C++ compatible conversions of FieldDescriptor::CppType's - namespace NCast { - template <ECppType src, ECppType dst> - struct TIsCompatibleCppType { - enum { - Result = src == dst || - (TIsNumericCppType<src>::Result && TIsNumericCppType<dst>::Result) - }; - }; + using ECppType = FieldDescriptor::CppType; - template <ECppType src, ECppType dst> - struct TIsEnumToNumericCppType { - enum { - Result = (src == FieldDescriptor::CPPTYPE_ENUM && TIsNumericCppType<dst>::Result) - }; + namespace NCast { + template <ECppType src, ECppType dst> + struct TIsCompatibleCppType { + enum { + Result = src == dst || + (TIsNumericCppType<src>::Result && TIsNumericCppType<dst>::Result) + }; }; - template <ECppType src, ECppType dst, bool compatible> // compatible == true - struct TCompatCastBase { - static const bool IsCompatible = true; - - typedef typename TCppTypeTraits<src>::T TSrc; - typedef typename TCppTypeTraits<dst>::T TDst; - - static inline TDst Cast(TSrc value) { - return value; - } + template <ECppType src, ECppType dst> + struct TIsEnumToNumericCppType { + enum { + Result = (src == FieldDescriptor::CPPTYPE_ENUM && TIsNumericCppType<dst>::Result) + }; }; - template <ECppType src, ECppType dst> // compatible == false - struct TCompatCastBase<src, dst, false> { - static const bool IsCompatible = false; - - typedef typename TCppTypeTraits<src>::T TSrc; - typedef typename TCppTypeTraits<dst>::T TDst; - - static inline TDst Cast(TSrc) { - ythrow TBadCastException() << "Incompatible FieldDescriptor::CppType conversion: #" - << (size_t)src << " to #" << (size_t)dst; - } - }; - - template <ECppType src, ECppType dst, bool isEnumToNum> // enum -> numeric - struct TCompatCastImpl { - static const bool IsCompatible = true; - - typedef typename TCppTypeTraits<dst>::T TDst; - - static inline TDst Cast(const EnumValueDescriptor* value) { - Y_ASSERT(value != nullptr); - return value->number(); - } - }; - - template <ECppType src, ECppType dst> - struct TCompatCastImpl<src, dst, false>: public TCompatCastBase<src, dst, TIsCompatibleCppType<src, dst>::Result> { - using TCompatCastBase<src, dst, TIsCompatibleCppType<src, dst>::Result>::IsCompatible; - }; - - template <ECppType src, ECppType dst> - struct TCompatCast: public TCompatCastImpl<src, dst, TIsEnumToNumericCppType<src, dst>::Result> { - typedef TCompatCastImpl<src, dst, TIsEnumToNumericCppType<src, dst>::Result> TBase; - - typedef typename TCppTypeTraits<src>::T TSrc; - typedef typename TCppTypeTraits<dst>::T TDst; - - using TBase::Cast; - using TBase::IsCompatible; - - inline bool Try(TSrc value, TDst& res) { - if (IsCompatible) { - res = Cast(value); - return true; - } - return false; - } - }; - - } - + template <ECppType src, ECppType dst, bool compatible> // compatible == true + struct TCompatCastBase { + static const bool IsCompatible = true; + + typedef typename TCppTypeTraits<src>::T TSrc; + typedef typename TCppTypeTraits<dst>::T TDst; + + static inline TDst Cast(TSrc value) { + return value; + } + }; + + template <ECppType src, ECppType dst> // compatible == false + struct TCompatCastBase<src, dst, false> { + static const bool IsCompatible = false; + + typedef typename TCppTypeTraits<src>::T TSrc; + typedef typename TCppTypeTraits<dst>::T TDst; + + static inline TDst Cast(TSrc) { + ythrow TBadCastException() << "Incompatible FieldDescriptor::CppType conversion: #" + << (size_t)src << " to #" << (size_t)dst; + } + }; + + template <ECppType src, ECppType dst, bool isEnumToNum> // enum -> numeric + struct TCompatCastImpl { + static const bool IsCompatible = true; + + typedef typename TCppTypeTraits<dst>::T TDst; + + static inline TDst Cast(const EnumValueDescriptor* value) { + Y_ASSERT(value != nullptr); + return value->number(); + } + }; + + template <ECppType src, ECppType dst> + struct TCompatCastImpl<src, dst, false>: public TCompatCastBase<src, dst, TIsCompatibleCppType<src, dst>::Result> { + using TCompatCastBase<src, dst, TIsCompatibleCppType<src, dst>::Result>::IsCompatible; + }; + + template <ECppType src, ECppType dst> + struct TCompatCast: public TCompatCastImpl<src, dst, TIsEnumToNumericCppType<src, dst>::Result> { + typedef TCompatCastImpl<src, dst, TIsEnumToNumericCppType<src, dst>::Result> TBase; + + typedef typename TCppTypeTraits<src>::T TSrc; + typedef typename TCppTypeTraits<dst>::T TDst; + + using TBase::Cast; + using TBase::IsCompatible; + + inline bool Try(TSrc value, TDst& res) { + if (IsCompatible) { + res = Cast(value); + return true; + } + return false; + } + }; + + } + template <ECppType src, ECppType dst> - inline typename TCppTypeTraits<dst>::T CompatCast(typename TCppTypeTraits<src>::T value) { - return NCast::TCompatCast<src, dst>::Cast(value); - } + inline typename TCppTypeTraits<dst>::T CompatCast(typename TCppTypeTraits<src>::T value) { + return NCast::TCompatCast<src, dst>::Cast(value); + } template <ECppType src, ECppType dst> - inline bool TryCompatCast(typename TCppTypeTraits<src>::T value, typename TCppTypeTraits<dst>::T& res) { - return NCast::TCompatCast<src, dst>::Try(value, res); - } - - // Message static/dynamic checked casts - - template <typename TpMessage> - inline const TpMessage* TryCast(const Message* msg) { - if (!msg || TpMessage::descriptor() != msg->GetDescriptor()) - return NULL; - return CheckedCast<const TpMessage*>(msg); - } - - template <typename TpMessage> - inline const TpMessage* TryCast(const Message* msg, const TpMessage*& ret) { - ret = TryCast<TpMessage>(msg); - return ret; - } - - template <typename TpMessage> - inline TpMessage* TryCast(Message* msg) { - if (!msg || TpMessage::descriptor() != msg->GetDescriptor()) - return nullptr; - return CheckedCast<TpMessage*>(msg); - } - - template <typename TpMessage> - inline TpMessage* TryCast(Message* msg, TpMessage*& ret) { - ret = TryCast<TpMessage>(msg); - return ret; - } - - // specialize for Message itself - - template <> - inline const Message* TryCast<Message>(const Message* msg) { - return msg; - } - - template <> - inline Message* TryCast<Message>(Message* msg) { - return msg; - } - - // Binary serialization compatible conversion - inline bool TryBinaryCast(const Message* from, Message* to, TString* buffer = nullptr) { - TString tmpbuf; - if (!buffer) - buffer = &tmpbuf; - - if (!from->SerializeToString(buffer)) - return false; - - return to->ParseFromString(*buffer); - } + inline bool TryCompatCast(typename TCppTypeTraits<src>::T value, typename TCppTypeTraits<dst>::T& res) { + return NCast::TCompatCast<src, dst>::Try(value, res); + } + + // Message static/dynamic checked casts + + template <typename TpMessage> + inline const TpMessage* TryCast(const Message* msg) { + if (!msg || TpMessage::descriptor() != msg->GetDescriptor()) + return NULL; + return CheckedCast<const TpMessage*>(msg); + } + + template <typename TpMessage> + inline const TpMessage* TryCast(const Message* msg, const TpMessage*& ret) { + ret = TryCast<TpMessage>(msg); + return ret; + } + + template <typename TpMessage> + inline TpMessage* TryCast(Message* msg) { + if (!msg || TpMessage::descriptor() != msg->GetDescriptor()) + return nullptr; + return CheckedCast<TpMessage*>(msg); + } + + template <typename TpMessage> + inline TpMessage* TryCast(Message* msg, TpMessage*& ret) { + ret = TryCast<TpMessage>(msg); + return ret; + } + + // specialize for Message itself + + template <> + inline const Message* TryCast<Message>(const Message* msg) { + return msg; + } + + template <> + inline Message* TryCast<Message>(Message* msg) { + return msg; + } + + // Binary serialization compatible conversion + inline bool TryBinaryCast(const Message* from, Message* to, TString* buffer = nullptr) { + TString tmpbuf; + if (!buffer) + buffer = &tmpbuf; + + if (!from->SerializeToString(buffer)) + return false; + + return to->ParseFromString(*buffer); + } } diff --git a/library/cpp/protobuf/util/is_equal.cpp b/library/cpp/protobuf/util/is_equal.cpp index 227408006e..f9711c9565 100644 --- a/library/cpp/protobuf/util/is_equal.cpp +++ b/library/cpp/protobuf/util/is_equal.cpp @@ -8,156 +8,156 @@ #include <util/string/vector.h> namespace NProtoBuf { - template <bool useDefault> - static bool IsEqualImpl(const Message& m1, const Message& m2, TVector<TString>* differentPath); - - namespace { - template <FieldDescriptor::CppType CppType, bool useDefault> - struct TCompareValue { - typedef typename TCppTypeTraits<CppType>::T T; - static inline bool IsEqual(T value1, T value2, TVector<TString>*) { - return value1 == value2; - } - }; - - template <bool useDefault> - struct TCompareValue<FieldDescriptor::CPPTYPE_MESSAGE, useDefault> { - static inline bool IsEqual(const Message* value1, const Message* value2, TVector<TString>* differentPath) { - return NProtoBuf::IsEqualImpl<useDefault>(*value1, *value2, differentPath); - } - }; - - template <FieldDescriptor::CppType CppType, bool useDefault> - class TCompareField { - typedef TCppTypeTraits<CppType> TTraits; - typedef TCompareValue<CppType, useDefault> TCompare; - - public: - static inline bool IsEqual(const Message& m1, const Message& m2, const FieldDescriptor& field, TVector<TString>* differentPath) { - if (field.is_repeated()) - return IsEqualRepeated(m1, m2, &field, differentPath); - else - return IsEqualSingle(m1, m2, &field, differentPath); - } - - private: - static bool IsEqualSingle(const Message& m1, const Message& m2, const FieldDescriptor* field, TVector<TString>* differentPath) { - bool has1 = m1.GetReflection()->HasField(m1, field); - bool has2 = m2.GetReflection()->HasField(m2, field); - - if (has1 != has2) { - if (!useDefault || field->is_required()) { - return false; - } - } else if (!has1) - return true; - - return TCompare::IsEqual(TTraits::Get(m1, field), - TTraits::Get(m2, field), - differentPath); - } - - static bool IsEqualRepeated(const Message& m1, const Message& m2, const FieldDescriptor* field, TVector<TString>* differentPath) { - int fieldSize = m1.GetReflection()->FieldSize(m1, field); - if (fieldSize != m2.GetReflection()->FieldSize(m2, field)) + template <bool useDefault> + static bool IsEqualImpl(const Message& m1, const Message& m2, TVector<TString>* differentPath); + + namespace { + template <FieldDescriptor::CppType CppType, bool useDefault> + struct TCompareValue { + typedef typename TCppTypeTraits<CppType>::T T; + static inline bool IsEqual(T value1, T value2, TVector<TString>*) { + return value1 == value2; + } + }; + + template <bool useDefault> + struct TCompareValue<FieldDescriptor::CPPTYPE_MESSAGE, useDefault> { + static inline bool IsEqual(const Message* value1, const Message* value2, TVector<TString>* differentPath) { + return NProtoBuf::IsEqualImpl<useDefault>(*value1, *value2, differentPath); + } + }; + + template <FieldDescriptor::CppType CppType, bool useDefault> + class TCompareField { + typedef TCppTypeTraits<CppType> TTraits; + typedef TCompareValue<CppType, useDefault> TCompare; + + public: + static inline bool IsEqual(const Message& m1, const Message& m2, const FieldDescriptor& field, TVector<TString>* differentPath) { + if (field.is_repeated()) + return IsEqualRepeated(m1, m2, &field, differentPath); + else + return IsEqualSingle(m1, m2, &field, differentPath); + } + + private: + static bool IsEqualSingle(const Message& m1, const Message& m2, const FieldDescriptor* field, TVector<TString>* differentPath) { + bool has1 = m1.GetReflection()->HasField(m1, field); + bool has2 = m2.GetReflection()->HasField(m2, field); + + if (has1 != has2) { + if (!useDefault || field->is_required()) { + return false; + } + } else if (!has1) + return true; + + return TCompare::IsEqual(TTraits::Get(m1, field), + TTraits::Get(m2, field), + differentPath); + } + + static bool IsEqualRepeated(const Message& m1, const Message& m2, const FieldDescriptor* field, TVector<TString>* differentPath) { + int fieldSize = m1.GetReflection()->FieldSize(m1, field); + if (fieldSize != m2.GetReflection()->FieldSize(m2, field)) return false; - for (int i = 0; i < fieldSize; ++i) - if (!IsEqualRepeatedValue(m1, m2, field, i, differentPath)) { - if (!!differentPath) { - differentPath->push_back(ToString(i)); - } - return false; - } + for (int i = 0; i < fieldSize; ++i) + if (!IsEqualRepeatedValue(m1, m2, field, i, differentPath)) { + if (!!differentPath) { + differentPath->push_back(ToString(i)); + } + return false; + } return true; - } - - static inline bool IsEqualRepeatedValue(const Message& m1, const Message& m2, const FieldDescriptor* field, int index, TVector<TString>* differentPath) { - return TCompare::IsEqual(TTraits::GetRepeated(m1, field, index), - TTraits::GetRepeated(m2, field, index), - differentPath); - } - }; - - template <bool useDefault> - bool IsEqualField(const Message& m1, const Message& m2, const FieldDescriptor& field, TVector<TString>* differentPath) { -#define CASE_CPPTYPE(cpptype) \ - case FieldDescriptor::CPPTYPE_##cpptype: { \ - bool r = TCompareField<FieldDescriptor::CPPTYPE_##cpptype, useDefault>::IsEqual(m1, m2, field, differentPath); \ - if (!r && !!differentPath) { \ - differentPath->push_back(field.name()); \ - } \ - return r; \ - } - - switch (field.cpp_type()) { - CASE_CPPTYPE(INT32) - CASE_CPPTYPE(INT64) - CASE_CPPTYPE(UINT32) - CASE_CPPTYPE(UINT64) - CASE_CPPTYPE(DOUBLE) - CASE_CPPTYPE(FLOAT) - CASE_CPPTYPE(BOOL) - CASE_CPPTYPE(ENUM) - CASE_CPPTYPE(STRING) - CASE_CPPTYPE(MESSAGE) - default: - ythrow yexception() << "Unsupported cpp-type field comparison"; - } - -#undef CASE_CPPTYPE + } + + static inline bool IsEqualRepeatedValue(const Message& m1, const Message& m2, const FieldDescriptor* field, int index, TVector<TString>* differentPath) { + return TCompare::IsEqual(TTraits::GetRepeated(m1, field, index), + TTraits::GetRepeated(m2, field, index), + differentPath); + } + }; + + template <bool useDefault> + bool IsEqualField(const Message& m1, const Message& m2, const FieldDescriptor& field, TVector<TString>* differentPath) { +#define CASE_CPPTYPE(cpptype) \ + case FieldDescriptor::CPPTYPE_##cpptype: { \ + bool r = TCompareField<FieldDescriptor::CPPTYPE_##cpptype, useDefault>::IsEqual(m1, m2, field, differentPath); \ + if (!r && !!differentPath) { \ + differentPath->push_back(field.name()); \ + } \ + return r; \ + } + + switch (field.cpp_type()) { + CASE_CPPTYPE(INT32) + CASE_CPPTYPE(INT64) + CASE_CPPTYPE(UINT32) + CASE_CPPTYPE(UINT64) + CASE_CPPTYPE(DOUBLE) + CASE_CPPTYPE(FLOAT) + CASE_CPPTYPE(BOOL) + CASE_CPPTYPE(ENUM) + CASE_CPPTYPE(STRING) + CASE_CPPTYPE(MESSAGE) + default: + ythrow yexception() << "Unsupported cpp-type field comparison"; + } + +#undef CASE_CPPTYPE } - } + } template <bool useDefault> - bool IsEqualImpl(const Message& m1, const Message& m2, TVector<TString>* differentPath) { - const Descriptor* descr = m1.GetDescriptor(); - if (descr != m2.GetDescriptor()) { - return false; + bool IsEqualImpl(const Message& m1, const Message& m2, TVector<TString>* differentPath) { + const Descriptor* descr = m1.GetDescriptor(); + if (descr != m2.GetDescriptor()) { + return false; } - for (int i = 0; i < descr->field_count(); ++i) - if (!IsEqualField<useDefault>(m1, m2, *descr->field(i), differentPath)) { - return false; - } - return true; - } - - bool IsEqual(const Message& m1, const Message& m2) { - return IsEqualImpl<false>(m1, m2, nullptr); - } - - bool IsEqual(const Message& m1, const Message& m2, TString* differentPath) { - TVector<TString> differentPathVector; - TVector<TString>* differentPathVectorPtr = !!differentPath ? &differentPathVector : nullptr; - bool r = IsEqualImpl<false>(m1, m2, differentPathVectorPtr); - if (!r && differentPath) { - *differentPath = JoinStrings(differentPathVector.rbegin(), differentPathVector.rend(), "/"); + for (int i = 0; i < descr->field_count(); ++i) + if (!IsEqualField<useDefault>(m1, m2, *descr->field(i), differentPath)) { + return false; + } + return true; + } + + bool IsEqual(const Message& m1, const Message& m2) { + return IsEqualImpl<false>(m1, m2, nullptr); + } + + bool IsEqual(const Message& m1, const Message& m2, TString* differentPath) { + TVector<TString> differentPathVector; + TVector<TString>* differentPathVectorPtr = !!differentPath ? &differentPathVector : nullptr; + bool r = IsEqualImpl<false>(m1, m2, differentPathVectorPtr); + if (!r && differentPath) { + *differentPath = JoinStrings(differentPathVector.rbegin(), differentPathVector.rend(), "/"); } - return r; - } + return r; + } - bool IsEqualDefault(const Message& m1, const Message& m2) { - return IsEqualImpl<true>(m1, m2, nullptr); + bool IsEqualDefault(const Message& m1, const Message& m2) { + return IsEqualImpl<true>(m1, m2, nullptr); } - template <bool useDefault> - static bool IsEqualFieldImpl( - const Message& m1, - const Message& m2, - const FieldDescriptor& field, - TVector<TString>* differentPath) { - const Descriptor* descr = m1.GetDescriptor(); - if (descr != m2.GetDescriptor()) { + template <bool useDefault> + static bool IsEqualFieldImpl( + const Message& m1, + const Message& m2, + const FieldDescriptor& field, + TVector<TString>* differentPath) { + const Descriptor* descr = m1.GetDescriptor(); + if (descr != m2.GetDescriptor()) { return false; } - return IsEqualField<useDefault>(m1, m2, field, differentPath); - } + return IsEqualField<useDefault>(m1, m2, field, differentPath); + } - bool IsEqualField(const Message& m1, const Message& m2, const FieldDescriptor& field) { - return IsEqualFieldImpl<false>(m1, m2, field, nullptr); + bool IsEqualField(const Message& m1, const Message& m2, const FieldDescriptor& field) { + return IsEqualFieldImpl<false>(m1, m2, field, nullptr); } - bool IsEqualFieldDefault(const Message& m1, const Message& m2, const FieldDescriptor& field) { - return IsEqualFieldImpl<true>(m1, m2, field, nullptr); + bool IsEqualFieldDefault(const Message& m1, const Message& m2, const FieldDescriptor& field) { + return IsEqualFieldImpl<true>(m1, m2, field, nullptr); } } diff --git a/library/cpp/protobuf/util/is_equal.h b/library/cpp/protobuf/util/is_equal.h index 13c0aae63d..46d38591ae 100644 --- a/library/cpp/protobuf/util/is_equal.h +++ b/library/cpp/protobuf/util/is_equal.h @@ -10,24 +10,24 @@ namespace google { } namespace NProtoBuf { - using ::google::protobuf::FieldDescriptor; + using ::google::protobuf::FieldDescriptor; using ::google::protobuf::Message; } namespace NProtoBuf { - // Reflection-based equality check for arbitrary protobuf messages + // Reflection-based equality check for arbitrary protobuf messages - // Strict comparison: optional field without value is NOT equal to - // a field with explicitly set default value. - bool IsEqual(const Message& m1, const Message& m2); - bool IsEqual(const Message& m1, const Message& m2, TString* differentPath); + // Strict comparison: optional field without value is NOT equal to + // a field with explicitly set default value. + bool IsEqual(const Message& m1, const Message& m2); + bool IsEqual(const Message& m1, const Message& m2, TString* differentPath); - bool IsEqualField(const Message& m1, const Message& m2, const FieldDescriptor& field); + bool IsEqualField(const Message& m1, const Message& m2, const FieldDescriptor& field); - // Non-strict version: optional field without explicit value is compared - // using its default value. - bool IsEqualDefault(const Message& m1, const Message& m2); + // Non-strict version: optional field without explicit value is compared + // using its default value. + bool IsEqualDefault(const Message& m1, const Message& m2); - bool IsEqualFieldDefault(const Message& m1, const Message& m2, const FieldDescriptor& field); + bool IsEqualFieldDefault(const Message& m1, const Message& m2, const FieldDescriptor& field); } diff --git a/library/cpp/protobuf/util/merge.cpp b/library/cpp/protobuf/util/merge.cpp index dc2b9cc806..258cbb737f 100644 --- a/library/cpp/protobuf/util/merge.cpp +++ b/library/cpp/protobuf/util/merge.cpp @@ -6,41 +6,41 @@ #include <library/cpp/protobuf/util/proto/merge.pb.h> namespace NProtoBuf { - void RewriteMerge(const Message& src, Message& dst) { - const Descriptor* d = src.GetDescriptor(); - Y_ASSERT(d == dst.GetDescriptor()); + void RewriteMerge(const Message& src, Message& dst) { + const Descriptor* d = src.GetDescriptor(); + Y_ASSERT(d == dst.GetDescriptor()); - for (int i = 0; i < d->field_count(); ++i) { - if (TConstField(src, d->field(i)).Has()) - TMutableField(dst, d->field(i)).Clear(); - } + for (int i = 0; i < d->field_count(); ++i) { + if (TConstField(src, d->field(i)).Has()) + TMutableField(dst, d->field(i)).Clear(); + } - dst.MergeFrom(src); + dst.MergeFrom(src); } - static void ClearNonMergeable(const Message& src, Message& dst) { - const Descriptor* d = src.GetDescriptor(); - if (d->options().GetExtension(DontMerge)) { - dst.Clear(); - return; - } - - for (int i = 0; i < d->field_count(); ++i) { - const FieldDescriptor* fd = d->field(i); - TConstField srcField(src, fd); - if (srcField.Has()) { - TMutableField dstField(dst, fd); - if (fd->options().GetExtension(DontMergeField)) - dstField.Clear(); - else if (!fd->is_repeated() && dstField.IsMessage() && dstField.Has()) - ClearNonMergeable(*srcField.Get<const Message*>(), *dstField.MutableMessage()); - } - } + static void ClearNonMergeable(const Message& src, Message& dst) { + const Descriptor* d = src.GetDescriptor(); + if (d->options().GetExtension(DontMerge)) { + dst.Clear(); + return; + } + + for (int i = 0; i < d->field_count(); ++i) { + const FieldDescriptor* fd = d->field(i); + TConstField srcField(src, fd); + if (srcField.Has()) { + TMutableField dstField(dst, fd); + if (fd->options().GetExtension(DontMergeField)) + dstField.Clear(); + else if (!fd->is_repeated() && dstField.IsMessage() && dstField.Has()) + ClearNonMergeable(*srcField.Get<const Message*>(), *dstField.MutableMessage()); + } + } } - void CustomMerge(const Message& src, Message& dst) { - ClearNonMergeable(src, dst); - dst.MergeFrom(src); + void CustomMerge(const Message& src, Message& dst) { + ClearNonMergeable(src, dst); + dst.MergeFrom(src); } } diff --git a/library/cpp/protobuf/util/merge.h b/library/cpp/protobuf/util/merge.h index 924975f141..b354331788 100644 --- a/library/cpp/protobuf/util/merge.h +++ b/library/cpp/protobuf/util/merge.h @@ -11,12 +11,12 @@ namespace NProtoBuf { } namespace NProtoBuf { - // Similiar to Message::MergeFrom, overwrites existing repeated fields - // and embedded messages completely instead of recursive merging. - void RewriteMerge(const Message& src, Message& dst); + // Similiar to Message::MergeFrom, overwrites existing repeated fields + // and embedded messages completely instead of recursive merging. + void RewriteMerge(const Message& src, Message& dst); - // Does standard MergeFrom() by default, except messages/fields marked with DontMerge or DontMergeField option. - // Such fields are merged using RewriteMerge() (i.e. destination is cleared before merging anything from source) - void CustomMerge(const Message& src, Message& dst); + // Does standard MergeFrom() by default, except messages/fields marked with DontMerge or DontMergeField option. + // Such fields are merged using RewriteMerge() (i.e. destination is cleared before merging anything from source) + void CustomMerge(const Message& src, Message& dst); -} +} diff --git a/library/cpp/protobuf/util/merge_ut.cpp b/library/cpp/protobuf/util/merge_ut.cpp index 22217db183..84b40c24b8 100644 --- a/library/cpp/protobuf/util/merge_ut.cpp +++ b/library/cpp/protobuf/util/merge_ut.cpp @@ -6,7 +6,7 @@ using namespace NProtoBuf; Y_UNIT_TEST_SUITE(ProtobufMerge) { - static void InitProto(NProtobufUtilUt::TMergeTest & p, bool isSrc) { + static void InitProto(NProtobufUtilUt::TMergeTest & p, bool isSrc) { size_t start = isSrc ? 0 : 100; p.AddMergeInt(start + 1); @@ -40,10 +40,10 @@ Y_UNIT_TEST_SUITE(ProtobufMerge) { InitProto(src, true); InitProto(dst, false); - // Cerr << "\nsrc: " << src.ShortDebugString() << Endl; - // Cerr << "dst: " << dst.ShortDebugString() << Endl; + // Cerr << "\nsrc: " << src.ShortDebugString() << Endl; + // Cerr << "dst: " << dst.ShortDebugString() << Endl; NProtoBuf::CustomMerge(src, dst); - // Cerr << "dst2:" << dst.ShortDebugString() << Endl; + // Cerr << "dst2:" << dst.ShortDebugString() << Endl; // repeated uint32 MergeInt = 1; UNIT_ASSERT_EQUAL(dst.MergeIntSize(), 4); diff --git a/library/cpp/protobuf/util/path.cpp b/library/cpp/protobuf/util/path.cpp index efa2a42c8a..aeb9b52b71 100644 --- a/library/cpp/protobuf/util/path.cpp +++ b/library/cpp/protobuf/util/path.cpp @@ -3,59 +3,59 @@ #include <util/generic/yexception.h> namespace NProtoBuf { - TFieldPath::TFieldPath() { - } - - TFieldPath::TFieldPath(const Descriptor* msgType, const TStringBuf& path) { - Init(msgType, path); - } - - TFieldPath::TFieldPath(const TVector<const FieldDescriptor*>& path) - : Path(path) - { - } - - bool TFieldPath::InitUnsafe(const Descriptor* msgType, TStringBuf path) { - Path.clear(); - while (path) { - TStringBuf next; - while (!next && path) - next = path.NextTok('/'); - if (!next) - return true; - - if (!msgType) // need field but no message type - return false; - - TString nextStr(next); - const FieldDescriptor* field = msgType->FindFieldByName(nextStr); - if (!field) { - // Try to find extension field by FindAllExtensions() - const DescriptorPool* pool = msgType->file()->pool(); - Y_ASSERT(pool); // never NULL by protobuf docs - TVector<const FieldDescriptor*> extensions; - pool->FindAllExtensions(msgType, &extensions); // find all extensions of this extendee - for (const FieldDescriptor* ext : extensions) { - if (ext->full_name() == nextStr || ext->name() == nextStr) { - if (field) - return false; // ambiguity - field = ext; - } + TFieldPath::TFieldPath() { + } + + TFieldPath::TFieldPath(const Descriptor* msgType, const TStringBuf& path) { + Init(msgType, path); + } + + TFieldPath::TFieldPath(const TVector<const FieldDescriptor*>& path) + : Path(path) + { + } + + bool TFieldPath::InitUnsafe(const Descriptor* msgType, TStringBuf path) { + Path.clear(); + while (path) { + TStringBuf next; + while (!next && path) + next = path.NextTok('/'); + if (!next) + return true; + + if (!msgType) // need field but no message type + return false; + + TString nextStr(next); + const FieldDescriptor* field = msgType->FindFieldByName(nextStr); + if (!field) { + // Try to find extension field by FindAllExtensions() + const DescriptorPool* pool = msgType->file()->pool(); + Y_ASSERT(pool); // never NULL by protobuf docs + TVector<const FieldDescriptor*> extensions; + pool->FindAllExtensions(msgType, &extensions); // find all extensions of this extendee + for (const FieldDescriptor* ext : extensions) { + if (ext->full_name() == nextStr || ext->name() == nextStr) { + if (field) + return false; // ambiguity + field = ext; + } } } - if (!field) - return false; - - Path.push_back(field); - msgType = field->type() == FieldDescriptor::TYPE_MESSAGE ? field->message_type() : nullptr; - } - return true; - } + if (!field) + return false; - void TFieldPath::Init(const Descriptor* msgType, const TStringBuf& path) { - if (!InitUnsafe(msgType, path)) - ythrow yexception() << "Failed to resolve path \"" << path << "\" relative to " << msgType->full_name(); + Path.push_back(field); + msgType = field->type() == FieldDescriptor::TYPE_MESSAGE ? field->message_type() : nullptr; + } + return true; } + void TFieldPath::Init(const Descriptor* msgType, const TStringBuf& path) { + if (!InitUnsafe(msgType, path)) + ythrow yexception() << "Failed to resolve path \"" << path << "\" relative to " << msgType->full_name(); + } + } diff --git a/library/cpp/protobuf/util/path.h b/library/cpp/protobuf/util/path.h index 487f643a2d..99cf198415 100644 --- a/library/cpp/protobuf/util/path.h +++ b/library/cpp/protobuf/util/path.h @@ -6,47 +6,47 @@ #include <util/generic/vector.h> namespace NProtoBuf { - class TFieldPath { - public: - TFieldPath(); - TFieldPath(const Descriptor* msgType, const TStringBuf& path); // throws exception if path doesn't exist - TFieldPath(const TVector<const FieldDescriptor*>& path); + class TFieldPath { + public: + TFieldPath(); + TFieldPath(const Descriptor* msgType, const TStringBuf& path); // throws exception if path doesn't exist + TFieldPath(const TVector<const FieldDescriptor*>& path); TFieldPath(const TFieldPath&) = default; TFieldPath& operator=(const TFieldPath&) = default; - bool InitUnsafe(const Descriptor* msgType, const TStringBuf path); // noexcept - void Init(const Descriptor* msgType, const TStringBuf& path); // throws + bool InitUnsafe(const Descriptor* msgType, const TStringBuf path); // noexcept + void Init(const Descriptor* msgType, const TStringBuf& path); // throws - const TVector<const FieldDescriptor*>& Fields() const { - return Path; - } + const TVector<const FieldDescriptor*>& Fields() const { + return Path; + } - void AddField(const FieldDescriptor* field) { - Path.push_back(field); - } + void AddField(const FieldDescriptor* field) { + Path.push_back(field); + } - const Descriptor* ParentType() const { - return Empty() ? nullptr : Path.front()->containing_type(); - } + const Descriptor* ParentType() const { + return Empty() ? nullptr : Path.front()->containing_type(); + } - const FieldDescriptor* FieldDescr() const { - return Empty() ? nullptr : Path.back(); - } + const FieldDescriptor* FieldDescr() const { + return Empty() ? nullptr : Path.back(); + } - bool Empty() const { - return Path.empty(); - } + bool Empty() const { + return Path.empty(); + } - explicit operator bool() const { - return !Empty(); - } + explicit operator bool() const { + return !Empty(); + } - bool operator!() const { - return Empty(); - } + bool operator!() const { + return Empty(); + } - private: - TVector<const FieldDescriptor*> Path; - }; + private: + TVector<const FieldDescriptor*> Path; + }; -} +} diff --git a/library/cpp/protobuf/util/pb_io.cpp b/library/cpp/protobuf/util/pb_io.cpp index 6270ee0624..f26b5322c9 100644 --- a/library/cpp/protobuf/util/pb_io.cpp +++ b/library/cpp/protobuf/util/pb_io.cpp @@ -23,50 +23,50 @@ namespace NProtoBuf { void ParseFromBase64String(const TStringBuf dataBase64, Message& m, bool allowUneven) { if (!m.ParseFromString(allowUneven ? Base64DecodeUneven(dataBase64) : Base64StrictDecode(dataBase64))) { - ythrow yexception() << "can't parse " << m.GetTypeName() << " from base64-encoded string"; - } - } + ythrow yexception() << "can't parse " << m.GetTypeName() << " from base64-encoded string"; + } + } bool TryParseFromBase64String(const TStringBuf dataBase64, Message& m, bool allowUneven) { - try { + try { ParseFromBase64String(dataBase64, m, allowUneven); - return true; - } catch (const std::exception&) { - return false; - } + return true; + } catch (const std::exception&) { + return false; + } } - void SerializeToBase64String(const Message& m, TString& dataBase64) { - TString rawData; - if (!m.SerializeToString(&rawData)) { - ythrow yexception() << "can't serialize " << m.GetTypeName(); - } - - Base64EncodeUrl(rawData, dataBase64); + void SerializeToBase64String(const Message& m, TString& dataBase64) { + TString rawData; + if (!m.SerializeToString(&rawData)) { + ythrow yexception() << "can't serialize " << m.GetTypeName(); + } + + Base64EncodeUrl(rawData, dataBase64); } - - TString SerializeToBase64String(const Message& m) { - TString s; - SerializeToBase64String(m, s); - return s; + + TString SerializeToBase64String(const Message& m) { + TString s; + SerializeToBase64String(m, s); + return s; } - bool TrySerializeToBase64String(const Message& m, TString& dataBase64) { - try { - SerializeToBase64String(m, dataBase64); - return true; - } catch (const std::exception&) { - return false; - } + bool TrySerializeToBase64String(const Message& m, TString& dataBase64) { + try { + SerializeToBase64String(m, dataBase64); + return true; + } catch (const std::exception&) { + return false; + } } - const TString ShortUtf8DebugString(const Message& message) { - TextFormat::Printer printer; - printer.SetSingleLineMode(true); - printer.SetUseUtf8StringEscaping(true); - TString result; - printer.PrintToString(message, &result); - return result; + const TString ShortUtf8DebugString(const Message& message) { + TextFormat::Printer printer; + printer.SetSingleLineMode(true); + printer.SetUseUtf8StringEscaping(true); + TString result; + printer.PrintToString(message, &result); + return result; } bool MergePartialFromString(NProtoBuf::Message& m, const TStringBuf serializedProtoMessage) { @@ -81,7 +81,7 @@ namespace NProtoBuf { } } -int operator&(NProtoBuf::Message& m, IBinSaver& f) { +int operator&(NProtoBuf::Message& m, IBinSaver& f) { TStringStream ss; if (f.IsReading()) { f.Add(0, &ss.Str()); diff --git a/library/cpp/protobuf/util/pb_io.h b/library/cpp/protobuf/util/pb_io.h index 493c84cb5f..261adf2b0e 100644 --- a/library/cpp/protobuf/util/pb_io.h +++ b/library/cpp/protobuf/util/pb_io.h @@ -40,9 +40,9 @@ namespace NProtoBuf { bool MergePartialFromString(NProtoBuf::Message& m, const TStringBuf serializedProtoMessage); bool MergeFromString(NProtoBuf::Message& m, const TStringBuf serializedProtoMessage); -} +} -int operator&(NProtoBuf::Message& m, IBinSaver& f); +int operator&(NProtoBuf::Message& m, IBinSaver& f); // Write a textual representation of the given message to the given file. void SerializeToTextFormat(const NProtoBuf::Message& m, const TString& fileName); diff --git a/library/cpp/protobuf/util/pb_io_ut.cpp b/library/cpp/protobuf/util/pb_io_ut.cpp index 875d6dc602..b81274b5ec 100644 --- a/library/cpp/protobuf/util/pb_io_ut.cpp +++ b/library/cpp/protobuf/util/pb_io_ut.cpp @@ -24,7 +24,7 @@ static NProtobufUtilUt::TTextEnumTest GetCorrectEnumMessage() { } static const TString CORRECT_MESSAGE = - R"(Foo: 42 + R"(Foo: 42 )"; static const TString CORRECT_ENUM_NAME_MESSAGE = R"(Slot: EET_SLOT_1 @@ -34,7 +34,7 @@ static const TString CORRECT_ENUM_ID_MESSAGE = )"; static const TString INCORRECT_MESSAGE = - R"(Bar: 1 + R"(Bar: 1 )"; static const TString INCORRECT_ENUM_NAME_MESSAGE = R"(Slot: EET_SLOT_3 @@ -177,8 +177,8 @@ Y_UNIT_TEST_SUITE(TTestProtoBufIO) { NProtobufUtilUt::TTextTest m; const auto f = [&correctFileName](NProtobufUtilUt::TTextTest& mm) { mm = ParseFromTextFormat<NProtobufUtilUt::TTextTest>( - correctFileName, - EParseFromTextFormatOption::AllowUnknownField); + correctFileName, + EParseFromTextFormatOption::AllowUnknownField); }; UNIT_ASSERT_NO_EXCEPTION(f(m)); UNIT_ASSERT(NProtoBuf::IsEqual(GetCorrectMessage(), m)); @@ -188,8 +188,8 @@ Y_UNIT_TEST_SUITE(TTestProtoBufIO) { NProtobufUtilUt::TTextTest m; const auto f = [&incorrectFileName](NProtobufUtilUt::TTextTest& mm) { mm = ParseFromTextFormat<NProtobufUtilUt::TTextTest>( - incorrectFileName, - EParseFromTextFormatOption::AllowUnknownField); + incorrectFileName, + EParseFromTextFormatOption::AllowUnknownField); }; UNIT_ASSERT_NO_EXCEPTION(f(m)); UNIT_ASSERT(NProtoBuf::IsEqual(empty, m)); @@ -354,8 +354,8 @@ Y_UNIT_TEST_SUITE(TTestProtoBufIO) { NProtobufUtilUt::TTextTest m; const auto f = [&correctFileName](NProtobufUtilUt::TTextTest& mm) { mm = MergeFromTextFormat<NProtobufUtilUt::TTextTest>( - correctFileName, - EParseFromTextFormatOption::AllowUnknownField); + correctFileName, + EParseFromTextFormatOption::AllowUnknownField); }; UNIT_ASSERT_NO_EXCEPTION(f(m)); UNIT_ASSERT(NProtoBuf::IsEqual(GetCorrectMessage(), m)); @@ -365,8 +365,8 @@ Y_UNIT_TEST_SUITE(TTestProtoBufIO) { NProtobufUtilUt::TTextTest m; const auto f = [&incorrectFileName](NProtobufUtilUt::TTextTest& mm) { mm = MergeFromTextFormat<NProtobufUtilUt::TTextTest>( - incorrectFileName, - EParseFromTextFormatOption::AllowUnknownField); + incorrectFileName, + EParseFromTextFormatOption::AllowUnknownField); }; UNIT_ASSERT_NO_EXCEPTION(f(m)); UNIT_ASSERT(NProtoBuf::IsEqual(empty, m)); diff --git a/library/cpp/protobuf/util/pb_utils.h b/library/cpp/protobuf/util/pb_utils.h index 9e9a110b48..71a76ff4c2 100644 --- a/library/cpp/protobuf/util/pb_utils.h +++ b/library/cpp/protobuf/util/pb_utils.h @@ -1,11 +1,11 @@ #pragma once #define UPDATE_PB_FIELD_MAX(PBMESS, FIELD, VAL) \ - if ((VAL) > (PBMESS).Get##FIELD()) { \ - (PBMESS).Set##FIELD(VAL); \ - } + if ((VAL) > (PBMESS).Get##FIELD()) { \ + (PBMESS).Set##FIELD(VAL); \ + } -#define UPDATE_OPT_PB_FIELD_MAX(PBMESS, FIELD, VAL) \ - if (!(PBMESS).Has##FIELD() || ((VAL) > (PBMESS).Get##FIELD())) { \ - (PBMESS).Set##FIELD(VAL); \ - } +#define UPDATE_OPT_PB_FIELD_MAX(PBMESS, FIELD, VAL) \ + if (!(PBMESS).Has##FIELD() || ((VAL) > (PBMESS).Get##FIELD())) { \ + (PBMESS).Set##FIELD(VAL); \ + } diff --git a/library/cpp/protobuf/util/repeated_field_utils.h b/library/cpp/protobuf/util/repeated_field_utils.h index c07bd84647..74767eaafe 100644 --- a/library/cpp/protobuf/util/repeated_field_utils.h +++ b/library/cpp/protobuf/util/repeated_field_utils.h @@ -6,8 +6,8 @@ template <typename T> void RemoveRepeatedPtrFieldElement(google::protobuf::RepeatedPtrField<T>* repeated, unsigned index) { google::protobuf::RepeatedPtrField<T> r; - Y_ASSERT(index < (unsigned)repeated->size()); - for (unsigned i = 0; i < (unsigned)repeated->size(); ++i) { + Y_ASSERT(index < (unsigned)repeated->size()); + for (unsigned i = 0; i < (unsigned)repeated->size(); ++i) { if (i == index) { continue; } @@ -17,80 +17,80 @@ void RemoveRepeatedPtrFieldElement(google::protobuf::RepeatedPtrField<T>* repeat } namespace NProtoBuf { - /// Move item to specified position - template <typename TRepeated> - static void MoveRepeatedFieldItem(TRepeated* field, size_t indexFrom, size_t indexTo) { - if (!field->size() || indexFrom >= static_cast<size_t>(field->size()) || indexFrom == indexTo) - return; - if (indexTo >= static_cast<size_t>(field->size())) - indexTo = field->size() - 1; - if (indexFrom > indexTo) { - for (size_t i = indexFrom; i > indexTo; --i) - field->SwapElements(i, i - 1); - } else { - for (size_t i = indexFrom; i < indexTo; ++i) - field->SwapElements(i, i + 1); - } - } + /// Move item to specified position + template <typename TRepeated> + static void MoveRepeatedFieldItem(TRepeated* field, size_t indexFrom, size_t indexTo) { + if (!field->size() || indexFrom >= static_cast<size_t>(field->size()) || indexFrom == indexTo) + return; + if (indexTo >= static_cast<size_t>(field->size())) + indexTo = field->size() - 1; + if (indexFrom > indexTo) { + for (size_t i = indexFrom; i > indexTo; --i) + field->SwapElements(i, i - 1); + } else { + for (size_t i = indexFrom; i < indexTo; ++i) + field->SwapElements(i, i + 1); + } + } - template <typename T> - static T* InsertRepeatedFieldItem(NProtoBuf::RepeatedPtrField<T>* field, size_t index) { - T* ret = field->Add(); - MoveRepeatedFieldItem(field, field->size() - 1, index); - return ret; + template <typename T> + static T* InsertRepeatedFieldItem(NProtoBuf::RepeatedPtrField<T>* field, size_t index) { + T* ret = field->Add(); + MoveRepeatedFieldItem(field, field->size() - 1, index); + return ret; } - template <typename TRepeated> // suitable both for RepeatedField and RepeatedPtrField - static void RemoveRepeatedFieldItem(TRepeated* field, size_t index) { - if ((int)index >= field->size()) - return; + template <typename TRepeated> // suitable both for RepeatedField and RepeatedPtrField + static void RemoveRepeatedFieldItem(TRepeated* field, size_t index) { + if ((int)index >= field->size()) + return; - for (int i = index + 1; i < field->size(); ++i) - field->SwapElements(i - 1, i); + for (int i = index + 1; i < field->size(); ++i) + field->SwapElements(i - 1, i); - field->RemoveLast(); - } + field->RemoveLast(); + } - template <typename TRepeated, typename TPred> // suitable both for RepeatedField and RepeatedPtrField - static void RemoveRepeatedFieldItemIf(TRepeated* repeated, TPred p) { - auto last = std::remove_if(repeated->begin(), repeated->end(), p); - if (last != repeated->end()) { - size_t countToRemove = repeated->end() - last; - while (countToRemove--) - repeated->RemoveLast(); - } - } + template <typename TRepeated, typename TPred> // suitable both for RepeatedField and RepeatedPtrField + static void RemoveRepeatedFieldItemIf(TRepeated* repeated, TPred p) { + auto last = std::remove_if(repeated->begin(), repeated->end(), p); + if (last != repeated->end()) { + size_t countToRemove = repeated->end() - last; + while (countToRemove--) + repeated->RemoveLast(); + } + } - namespace NImpl { - template <typename TRepeated> - static void ShiftLeft(TRepeated* field, int begIndex, int endIndex, size_t shiftSize) { - Y_ASSERT(begIndex <= field->size()); - Y_ASSERT(endIndex <= field->size()); - size_t shiftIndex = (int)shiftSize < begIndex ? begIndex - shiftSize : 0; - for (int i = begIndex; i < endIndex; ++i, ++shiftIndex) - field->SwapElements(shiftIndex, i); - } + namespace NImpl { + template <typename TRepeated> + static void ShiftLeft(TRepeated* field, int begIndex, int endIndex, size_t shiftSize) { + Y_ASSERT(begIndex <= field->size()); + Y_ASSERT(endIndex <= field->size()); + size_t shiftIndex = (int)shiftSize < begIndex ? begIndex - shiftSize : 0; + for (int i = begIndex; i < endIndex; ++i, ++shiftIndex) + field->SwapElements(shiftIndex, i); + } } - // Remove several items at once, could be more efficient compared to calling RemoveRepeatedFieldItem several times + // Remove several items at once, could be more efficient compared to calling RemoveRepeatedFieldItem several times template <typename TRepeated> - static void RemoveRepeatedFieldItems(TRepeated* field, const TVector<size_t>& sortedIndices) { - if (sortedIndices.empty()) - return; + static void RemoveRepeatedFieldItems(TRepeated* field, const TVector<size_t>& sortedIndices) { + if (sortedIndices.empty()) + return; - size_t shift = 1; - for (size_t i = 1; i < sortedIndices.size(); ++i, ++shift) - NImpl::ShiftLeft(field, sortedIndices[i - 1] + 1, sortedIndices[i], shift); - NImpl::ShiftLeft(field, sortedIndices.back() + 1, field->size(), shift); + size_t shift = 1; + for (size_t i = 1; i < sortedIndices.size(); ++i, ++shift) + NImpl::ShiftLeft(field, sortedIndices[i - 1] + 1, sortedIndices[i], shift); + NImpl::ShiftLeft(field, sortedIndices.back() + 1, field->size(), shift); - for (; shift > 0; --shift) - field->RemoveLast(); - } + for (; shift > 0; --shift) + field->RemoveLast(); + } - template <typename TRepeated> - static void ReverseRepeatedFieldItems(TRepeated* field) { - for (int i1 = 0, i2 = field->size() - 1; i1 < i2; ++i1, --i2) - field->SwapElements(i1, i2); - } + template <typename TRepeated> + static void ReverseRepeatedFieldItems(TRepeated* field) { + for (int i1 = 0, i2 = field->size() - 1; i1 < i2; ++i1, --i2) + field->SwapElements(i1, i2); + } } diff --git a/library/cpp/protobuf/util/simple_reflection.cpp b/library/cpp/protobuf/util/simple_reflection.cpp index d842e9ee44..913a011028 100644 --- a/library/cpp/protobuf/util/simple_reflection.cpp +++ b/library/cpp/protobuf/util/simple_reflection.cpp @@ -1,70 +1,70 @@ #include "simple_reflection.h" namespace NProtoBuf { - const Message* GetMessageHelper(const TConstField& curField, bool) { - return curField.HasValue() && curField.IsMessage() ? curField.Get<Message>() : nullptr; - } + const Message* GetMessageHelper(const TConstField& curField, bool) { + return curField.HasValue() && curField.IsMessage() ? curField.Get<Message>() : nullptr; + } - Message* GetMessageHelper(TMutableField& curField, bool createPath) { - if (curField.IsMessage()) { - if (!curField.HasValue()) { - if (createPath) - return curField.Field()->is_repeated() ? curField.AddMessage() : curField.MutableMessage(); - } else { - return curField.MutableMessage(); - } + Message* GetMessageHelper(TMutableField& curField, bool createPath) { + if (curField.IsMessage()) { + if (!curField.HasValue()) { + if (createPath) + return curField.Field()->is_repeated() ? curField.AddMessage() : curField.MutableMessage(); + } else { + return curField.MutableMessage(); + } } - return nullptr; + return nullptr; } - template <class TField, class TMsg> - TMaybe<TField> ByPathImpl(TMsg& msg, const TVector<const FieldDescriptor*>& fieldsPath, bool createPath) { - if (fieldsPath.empty()) - return TMaybe<TField>(); - TMsg* curParent = &msg; - for (size_t i = 0, size = fieldsPath.size(); i < size; ++i) { - const FieldDescriptor* field = fieldsPath[i]; - if (!curParent) - return TMaybe<TField>(); - TField curField(*curParent, field); - if (size - i == 1) // last element in path - return curField; - curParent = GetMessageHelper(curField, createPath); - } - if (curParent) - return TField(*curParent, fieldsPath.back()); - else + template <class TField, class TMsg> + TMaybe<TField> ByPathImpl(TMsg& msg, const TVector<const FieldDescriptor*>& fieldsPath, bool createPath) { + if (fieldsPath.empty()) return TMaybe<TField>(); + TMsg* curParent = &msg; + for (size_t i = 0, size = fieldsPath.size(); i < size; ++i) { + const FieldDescriptor* field = fieldsPath[i]; + if (!curParent) + return TMaybe<TField>(); + TField curField(*curParent, field); + if (size - i == 1) // last element in path + return curField; + curParent = GetMessageHelper(curField, createPath); + } + if (curParent) + return TField(*curParent, fieldsPath.back()); + else + return TMaybe<TField>(); } - TMaybe<TConstField> TConstField::ByPath(const Message& msg, const TVector<const FieldDescriptor*>& fieldsPath) { - return ByPathImpl<TConstField, const Message>(msg, fieldsPath, false); - } - - TMaybe<TConstField> TConstField::ByPath(const Message& msg, const TStringBuf& path) { - TFieldPath fieldPath; - if (!fieldPath.InitUnsafe(msg.GetDescriptor(), path)) - return TMaybe<TConstField>(); - return ByPathImpl<TConstField, const Message>(msg, fieldPath.Fields(), false); - } + TMaybe<TConstField> TConstField::ByPath(const Message& msg, const TVector<const FieldDescriptor*>& fieldsPath) { + return ByPathImpl<TConstField, const Message>(msg, fieldsPath, false); + } - TMaybe<TConstField> TConstField::ByPath(const Message& msg, const TFieldPath& path) { - return ByPathImpl<TConstField, const Message>(msg, path.Fields(), false); - } + TMaybe<TConstField> TConstField::ByPath(const Message& msg, const TStringBuf& path) { + TFieldPath fieldPath; + if (!fieldPath.InitUnsafe(msg.GetDescriptor(), path)) + return TMaybe<TConstField>(); + return ByPathImpl<TConstField, const Message>(msg, fieldPath.Fields(), false); + } - TMaybe<TMutableField> TMutableField::ByPath(Message& msg, const TVector<const FieldDescriptor*>& fieldsPath, bool createPath) { - return ByPathImpl<TMutableField, Message>(msg, fieldsPath, createPath); - } + TMaybe<TConstField> TConstField::ByPath(const Message& msg, const TFieldPath& path) { + return ByPathImpl<TConstField, const Message>(msg, path.Fields(), false); + } - TMaybe<TMutableField> TMutableField::ByPath(Message& msg, const TStringBuf& path, bool createPath) { - TFieldPath fieldPath; - if (!fieldPath.InitUnsafe(msg.GetDescriptor(), path)) - return TMaybe<TMutableField>(); - return ByPathImpl<TMutableField, Message>(msg, fieldPath.Fields(), createPath); - } + TMaybe<TMutableField> TMutableField::ByPath(Message& msg, const TVector<const FieldDescriptor*>& fieldsPath, bool createPath) { + return ByPathImpl<TMutableField, Message>(msg, fieldsPath, createPath); + } - TMaybe<TMutableField> TMutableField::ByPath(Message& msg, const TFieldPath& path, bool createPath) { - return ByPathImpl<TMutableField, Message>(msg, path.Fields(), createPath); - } + TMaybe<TMutableField> TMutableField::ByPath(Message& msg, const TStringBuf& path, bool createPath) { + TFieldPath fieldPath; + if (!fieldPath.InitUnsafe(msg.GetDescriptor(), path)) + return TMaybe<TMutableField>(); + return ByPathImpl<TMutableField, Message>(msg, fieldPath.Fields(), createPath); + } + TMaybe<TMutableField> TMutableField::ByPath(Message& msg, const TFieldPath& path, bool createPath) { + return ByPathImpl<TMutableField, Message>(msg, path.Fields(), createPath); + } + } diff --git a/library/cpp/protobuf/util/simple_reflection.h b/library/cpp/protobuf/util/simple_reflection.h index 61e877a787..172de02f78 100644 --- a/library/cpp/protobuf/util/simple_reflection.h +++ b/library/cpp/protobuf/util/simple_reflection.h @@ -13,137 +13,137 @@ #include <util/system/defaults.h> namespace NProtoBuf { - class TConstField { - public: - TConstField(const Message& msg, const FieldDescriptor* fd) - : Msg(msg) - , Fd(fd) - { - Y_ASSERT(Fd && Fd->containing_type() == Msg.GetDescriptor()); - } - - static TMaybe<TConstField> ByPath(const Message& msg, const TStringBuf& path); - static TMaybe<TConstField> ByPath(const Message& msg, const TVector<const FieldDescriptor*>& fieldsPath); - static TMaybe<TConstField> ByPath(const Message& msg, const TFieldPath& fieldsPath); - - const Message& Parent() const { - return Msg; - } - - const FieldDescriptor* Field() const { - return Fd; - } - - bool HasValue() const { - return IsRepeated() ? Refl().FieldSize(Msg, Fd) > 0 - : Refl().HasField(Msg, Fd); - } - - // deprecated, use HasValue() instead - bool Has() const { - return HasValue(); - } - - size_t Size() const { - return IsRepeated() ? Refl().FieldSize(Msg, Fd) - : (Refl().HasField(Msg, Fd) ? 1 : 0); - } - - template <typename T> - inline typename TSelectCppType<T>::T Get(size_t index = 0) const; - - template <typename TMsg> - inline const TMsg* GetAs(size_t index = 0) const { - // casting version of Get - return IsMessageInstance<TMsg>() ? CheckedCast<const TMsg*>(Get<const Message*>(index)) : nullptr; - } - - template <typename T> - bool IsInstance() const { - return CppType() == TSelectCppType<T>::Result; - } - - template <typename TMsg> - bool IsMessageInstance() const { - return IsMessage() && Fd->message_type() == TMsg::descriptor(); - } - - template <typename TMsg> - bool IsInstance(std::enable_if_t<std::is_base_of<Message, TMsg>::value && !std::is_same<Message, TMsg>::value, void>* = NULL) const { // template will be selected when specifying Message children types - return IsMessage() && Fd->message_type() == TMsg::descriptor(); - } - - bool IsString() const { - return CppType() == FieldDescriptor::CPPTYPE_STRING; - } - - bool IsMessage() const { - return CppType() == FieldDescriptor::CPPTYPE_MESSAGE; - } - - bool HasSameType(const TConstField& other) const { - if (CppType() != other.CppType()) - return false; - if (IsMessage() && Field()->message_type() != other.Field()->message_type()) - return false; - if (CppType() == FieldDescriptor::CPPTYPE_ENUM && Field()->enum_type() != other.Field()->enum_type()) - return false; - return true; - } - - protected: - bool IsRepeated() const { - return Fd->is_repeated(); - } - - FieldDescriptor::CppType CppType() const { - return Fd->cpp_type(); - } - - const Reflection& Refl() const { - return *Msg.GetReflection(); - } + class TConstField { + public: + TConstField(const Message& msg, const FieldDescriptor* fd) + : Msg(msg) + , Fd(fd) + { + Y_ASSERT(Fd && Fd->containing_type() == Msg.GetDescriptor()); + } + + static TMaybe<TConstField> ByPath(const Message& msg, const TStringBuf& path); + static TMaybe<TConstField> ByPath(const Message& msg, const TVector<const FieldDescriptor*>& fieldsPath); + static TMaybe<TConstField> ByPath(const Message& msg, const TFieldPath& fieldsPath); + + const Message& Parent() const { + return Msg; + } + + const FieldDescriptor* Field() const { + return Fd; + } + + bool HasValue() const { + return IsRepeated() ? Refl().FieldSize(Msg, Fd) > 0 + : Refl().HasField(Msg, Fd); + } + + // deprecated, use HasValue() instead + bool Has() const { + return HasValue(); + } + + size_t Size() const { + return IsRepeated() ? Refl().FieldSize(Msg, Fd) + : (Refl().HasField(Msg, Fd) ? 1 : 0); + } + + template <typename T> + inline typename TSelectCppType<T>::T Get(size_t index = 0) const; + + template <typename TMsg> + inline const TMsg* GetAs(size_t index = 0) const { + // casting version of Get + return IsMessageInstance<TMsg>() ? CheckedCast<const TMsg*>(Get<const Message*>(index)) : nullptr; + } + + template <typename T> + bool IsInstance() const { + return CppType() == TSelectCppType<T>::Result; + } + + template <typename TMsg> + bool IsMessageInstance() const { + return IsMessage() && Fd->message_type() == TMsg::descriptor(); + } + + template <typename TMsg> + bool IsInstance(std::enable_if_t<std::is_base_of<Message, TMsg>::value && !std::is_same<Message, TMsg>::value, void>* = NULL) const { // template will be selected when specifying Message children types + return IsMessage() && Fd->message_type() == TMsg::descriptor(); + } + + bool IsString() const { + return CppType() == FieldDescriptor::CPPTYPE_STRING; + } + + bool IsMessage() const { + return CppType() == FieldDescriptor::CPPTYPE_MESSAGE; + } + + bool HasSameType(const TConstField& other) const { + if (CppType() != other.CppType()) + return false; + if (IsMessage() && Field()->message_type() != other.Field()->message_type()) + return false; + if (CppType() == FieldDescriptor::CPPTYPE_ENUM && Field()->enum_type() != other.Field()->enum_type()) + return false; + return true; + } + + protected: + bool IsRepeated() const { + return Fd->is_repeated(); + } + + FieldDescriptor::CppType CppType() const { + return Fd->cpp_type(); + } + + const Reflection& Refl() const { + return *Msg.GetReflection(); + } [[noreturn]] void RaiseUnknown() const { - ythrow yexception() << "Unknown field cpp-type: " << (size_t)CppType(); - } + ythrow yexception() << "Unknown field cpp-type: " << (size_t)CppType(); + } - bool IsSameField(const TConstField& other) const { - return &Parent() == &other.Parent() && Field() == other.Field(); - } + bool IsSameField(const TConstField& other) const { + return &Parent() == &other.Parent() && Field() == other.Field(); + } - protected: - const Message& Msg; - const FieldDescriptor* Fd; - }; + protected: + const Message& Msg; + const FieldDescriptor* Fd; + }; - class TMutableField: public TConstField { - public: - TMutableField(Message& msg, const FieldDescriptor* fd) - : TConstField(msg, fd) - { - } + class TMutableField: public TConstField { + public: + TMutableField(Message& msg, const FieldDescriptor* fd) + : TConstField(msg, fd) + { + } - static TMaybe<TMutableField> ByPath(Message& msg, const TStringBuf& path, bool createPath = false); - static TMaybe<TMutableField> ByPath(Message& msg, const TVector<const FieldDescriptor*>& fieldsPath, bool createPath = false); - static TMaybe<TMutableField> ByPath(Message& msg, const TFieldPath& fieldsPath, bool createPath = false); + static TMaybe<TMutableField> ByPath(Message& msg, const TStringBuf& path, bool createPath = false); + static TMaybe<TMutableField> ByPath(Message& msg, const TVector<const FieldDescriptor*>& fieldsPath, bool createPath = false); + static TMaybe<TMutableField> ByPath(Message& msg, const TFieldPath& fieldsPath, bool createPath = false); - Message* MutableParent() { - return Mut(); - } + Message* MutableParent() { + return Mut(); + } - template <typename T> - inline void Set(T value, size_t index = 0); + template <typename T> + inline void Set(T value, size_t index = 0); - template <typename T> - inline void Add(T value); + template <typename T> + inline void Add(T value); - inline void MergeFrom(const TConstField& src); + inline void MergeFrom(const TConstField& src); - inline void Clear() { - Refl().ClearField(Mut(), Fd); - } - /* + inline void Clear() { + Refl().ClearField(Mut(), Fd); + } + /* void Swap(TMutableField& f) { Y_ASSERT(Field() == f.Field()); @@ -151,139 +151,139 @@ namespace NProtoBuf { // is ported into arcadia protobuf library from up-stream. } */ - inline void RemoveLast() { - Y_ASSERT(HasValue()); - if (IsRepeated()) - Refl().RemoveLast(Mut(), Fd); - else - Clear(); - } - - inline void SwapElements(size_t index1, size_t index2) { - Y_ASSERT(IsRepeated()); - Y_ASSERT(index1 < Size()); - Y_ASSERT(index2 < Size()); - if (index1 == index2) - return; - Refl().SwapElements(Mut(), Fd, index1, index2); - } - - inline void Remove(size_t index) { - if (index >= Size()) - return; - - // Move to the end - for (size_t i = index, size = Size(); i < size - 1; ++i) - SwapElements(i, i + 1); - RemoveLast(); - } - - Message* MutableMessage(size_t index = 0) { - Y_ASSERT(IsMessage()); - if (IsRepeated()) { - Y_ASSERT(index < Size()); - return Refl().MutableRepeatedMessage(Mut(), Fd, index); - } else { - Y_ASSERT(index == 0); - return Refl().MutableMessage(Mut(), Fd); - } - } - - template <typename TMsg> - inline TMsg* AddMessage() { - return CheckedCast<TMsg*>(AddMessage()); - } - - inline Message* AddMessage() { - Y_ASSERT(IsMessage() && IsRepeated()); - return Refl().AddMessage(Mut(), Fd); - } - - private: - Message* Mut() { - return const_cast<Message*>(&Msg); - } - - template <typename T> - inline void MergeValue(T srcValue); - }; - - // template implementations - - template <typename T> - inline typename TSelectCppType<T>::T TConstField::Get(size_t index) const { - Y_ASSERT(index < Size() || !Fd->is_repeated() && index == 0); // Get for single fields is always allowed because of default values -#define TMP_MACRO_FOR_CPPTYPE(CPPTYPE) \ - case CPPTYPE: \ - return CompatCast<CPPTYPE, TSelectCppType<T>::Result>(TSimpleFieldTraits<CPPTYPE>::Get(Msg, Fd, index)); - switch (CppType()) { - APPLY_TMP_MACRO_FOR_ALL_CPPTYPES() - default: - RaiseUnknown(); - } -#undef TMP_MACRO_FOR_CPPTYPE + inline void RemoveLast() { + Y_ASSERT(HasValue()); + if (IsRepeated()) + Refl().RemoveLast(Mut(), Fd); + else + Clear(); + } + + inline void SwapElements(size_t index1, size_t index2) { + Y_ASSERT(IsRepeated()); + Y_ASSERT(index1 < Size()); + Y_ASSERT(index2 < Size()); + if (index1 == index2) + return; + Refl().SwapElements(Mut(), Fd, index1, index2); + } + + inline void Remove(size_t index) { + if (index >= Size()) + return; + + // Move to the end + for (size_t i = index, size = Size(); i < size - 1; ++i) + SwapElements(i, i + 1); + RemoveLast(); + } + + Message* MutableMessage(size_t index = 0) { + Y_ASSERT(IsMessage()); + if (IsRepeated()) { + Y_ASSERT(index < Size()); + return Refl().MutableRepeatedMessage(Mut(), Fd, index); + } else { + Y_ASSERT(index == 0); + return Refl().MutableMessage(Mut(), Fd); + } + } + + template <typename TMsg> + inline TMsg* AddMessage() { + return CheckedCast<TMsg*>(AddMessage()); + } + + inline Message* AddMessage() { + Y_ASSERT(IsMessage() && IsRepeated()); + return Refl().AddMessage(Mut(), Fd); + } + + private: + Message* Mut() { + return const_cast<Message*>(&Msg); + } + + template <typename T> + inline void MergeValue(T srcValue); + }; + + // template implementations + + template <typename T> + inline typename TSelectCppType<T>::T TConstField::Get(size_t index) const { + Y_ASSERT(index < Size() || !Fd->is_repeated() && index == 0); // Get for single fields is always allowed because of default values +#define TMP_MACRO_FOR_CPPTYPE(CPPTYPE) \ + case CPPTYPE: \ + return CompatCast<CPPTYPE, TSelectCppType<T>::Result>(TSimpleFieldTraits<CPPTYPE>::Get(Msg, Fd, index)); + switch (CppType()) { + APPLY_TMP_MACRO_FOR_ALL_CPPTYPES() + default: + RaiseUnknown(); + } +#undef TMP_MACRO_FOR_CPPTYPE } - template <typename T> - inline void TMutableField::Set(T value, size_t index) { - Y_ASSERT(!IsRepeated() && index == 0 || index < Size()); -#define TMP_MACRO_FOR_CPPTYPE(CPPTYPE) \ - case CPPTYPE: \ - TSimpleFieldTraits<CPPTYPE>::Set(*Mut(), Fd, CompatCast<TSelectCppType<T>::Result, CPPTYPE>(value), index); \ - break; - switch (CppType()) { - APPLY_TMP_MACRO_FOR_ALL_CPPTYPES() - default: - RaiseUnknown(); - } -#undef TMP_MACRO_FOR_CPPTYPE + template <typename T> + inline void TMutableField::Set(T value, size_t index) { + Y_ASSERT(!IsRepeated() && index == 0 || index < Size()); +#define TMP_MACRO_FOR_CPPTYPE(CPPTYPE) \ + case CPPTYPE: \ + TSimpleFieldTraits<CPPTYPE>::Set(*Mut(), Fd, CompatCast<TSelectCppType<T>::Result, CPPTYPE>(value), index); \ + break; + switch (CppType()) { + APPLY_TMP_MACRO_FOR_ALL_CPPTYPES() + default: + RaiseUnknown(); + } +#undef TMP_MACRO_FOR_CPPTYPE } - template <typename T> - inline void TMutableField::Add(T value) { -#define TMP_MACRO_FOR_CPPTYPE(CPPTYPE) \ - case CPPTYPE: \ - TSimpleFieldTraits<CPPTYPE>::Add(*Mut(), Fd, CompatCast<TSelectCppType<T>::Result, CPPTYPE>(value)); \ - break; - switch (CppType()) { - APPLY_TMP_MACRO_FOR_ALL_CPPTYPES() - default: - RaiseUnknown(); - } -#undef TMP_MACRO_FOR_CPPTYPE + template <typename T> + inline void TMutableField::Add(T value) { +#define TMP_MACRO_FOR_CPPTYPE(CPPTYPE) \ + case CPPTYPE: \ + TSimpleFieldTraits<CPPTYPE>::Add(*Mut(), Fd, CompatCast<TSelectCppType<T>::Result, CPPTYPE>(value)); \ + break; + switch (CppType()) { + APPLY_TMP_MACRO_FOR_ALL_CPPTYPES() + default: + RaiseUnknown(); + } +#undef TMP_MACRO_FOR_CPPTYPE } - template <typename T> - inline void TMutableField::MergeValue(T srcValue) { + template <typename T> + inline void TMutableField::MergeValue(T srcValue) { Add(srcValue); } - template <> - inline void TMutableField::MergeValue<const Message*>(const Message* srcValue) { - if (IsRepeated()) { - Add(srcValue); - } else { - MutableMessage()->MergeFrom(*srcValue); + template <> + inline void TMutableField::MergeValue<const Message*>(const Message* srcValue) { + if (IsRepeated()) { + Add(srcValue); + } else { + MutableMessage()->MergeFrom(*srcValue); } } - - inline void TMutableField::MergeFrom(const TConstField& src) { - Y_ASSERT(HasSameType(src)); - if (IsSameField(src)) - return; -#define TMP_MACRO_FOR_CPPTYPE(CPPTYPE) \ - case CPPTYPE: { \ - for (size_t itemIdx = 0; itemIdx < src.Size(); ++itemIdx) { \ - MergeValue(TSimpleFieldTraits<CPPTYPE>::Get(src.Parent(), src.Field(), itemIdx)); \ - } \ - break; \ - } - switch (CppType()) { - APPLY_TMP_MACRO_FOR_ALL_CPPTYPES() - default: - RaiseUnknown(); - } -#undef TMP_MACRO_FOR_CPPTYPE - } - + + inline void TMutableField::MergeFrom(const TConstField& src) { + Y_ASSERT(HasSameType(src)); + if (IsSameField(src)) + return; +#define TMP_MACRO_FOR_CPPTYPE(CPPTYPE) \ + case CPPTYPE: { \ + for (size_t itemIdx = 0; itemIdx < src.Size(); ++itemIdx) { \ + MergeValue(TSimpleFieldTraits<CPPTYPE>::Get(src.Parent(), src.Field(), itemIdx)); \ + } \ + break; \ + } + switch (CppType()) { + APPLY_TMP_MACRO_FOR_ALL_CPPTYPES() + default: + RaiseUnknown(); + } +#undef TMP_MACRO_FOR_CPPTYPE + } + } diff --git a/library/cpp/protobuf/util/simple_reflection_ut.cpp b/library/cpp/protobuf/util/simple_reflection_ut.cpp index 169d4703c9..4b6d6e715d 100644 --- a/library/cpp/protobuf/util/simple_reflection_ut.cpp +++ b/library/cpp/protobuf/util/simple_reflection_ut.cpp @@ -36,7 +36,7 @@ Y_UNIT_TEST_SUITE(ProtobufSimpleReflection) { dstOneMsg.MergeFrom(TConstField(src, descr->FindFieldByName("OneMsg"))); UNIT_ASSERT_VALUES_EQUAL(dst.GetOneMsg().RepIntSize(), src.GetOneMsg().RepIntSize()); dstOneMsg.MergeFrom(TConstField(src, descr->FindFieldByName("OneMsg"))); - UNIT_ASSERT_VALUES_EQUAL(dst.GetOneMsg().RepIntSize(), src.GetOneMsg().RepIntSize() * 2); + UNIT_ASSERT_VALUES_EQUAL(dst.GetOneMsg().RepIntSize(), src.GetOneMsg().RepIntSize() * 2); } { // MergeFrom for repeated fields acts like append @@ -44,7 +44,7 @@ Y_UNIT_TEST_SUITE(ProtobufSimpleReflection) { dstRepMsg.MergeFrom(TConstField(src, descr->FindFieldByName("RepMsg"))); UNIT_ASSERT_VALUES_EQUAL(dst.RepMsgSize(), src.RepMsgSize()); dstRepMsg.MergeFrom(TConstField(src, descr->FindFieldByName("RepMsg"))); - UNIT_ASSERT_VALUES_EQUAL(dst.RepMsgSize(), src.RepMsgSize() * 2); + UNIT_ASSERT_VALUES_EQUAL(dst.RepMsgSize(), src.RepMsgSize() * 2); for (size_t repMsgIndex = 0; repMsgIndex < dst.RepMsgSize(); ++repMsgIndex) { UNIT_ASSERT_VALUES_EQUAL(dst.GetRepMsg(repMsgIndex).RepIntSize(), src.GetRepMsg(0).RepIntSize()); } @@ -107,14 +107,14 @@ Y_UNIT_TEST_SUITE(ProtobufSimpleReflection) { msg.AddRepMsg()->AddRepInt(3); UNIT_ASSERT_VALUES_EQUAL(3, msg.RepMsgSize()); // 1, 2, 3 - fld.Remove(1); // from middle + fld.Remove(1); // from middle UNIT_ASSERT_VALUES_EQUAL(2, msg.RepMsgSize()); UNIT_ASSERT_VALUES_EQUAL(1, msg.GetRepMsg(0).GetRepInt(0)); UNIT_ASSERT_VALUES_EQUAL(3, msg.GetRepMsg(1).GetRepInt(0)); msg.AddRepMsg()->AddRepInt(5); UNIT_ASSERT_VALUES_EQUAL(3, msg.RepMsgSize()); // 1, 3, 5 - fld.Remove(2); // from end + fld.Remove(2); // from end UNIT_ASSERT_VALUES_EQUAL(2, msg.RepMsgSize()); UNIT_ASSERT_VALUES_EQUAL(1, msg.GetRepMsg(0).GetRepInt(0)); UNIT_ASSERT_VALUES_EQUAL(3, msg.GetRepMsg(1).GetRepInt(0)); @@ -127,7 +127,7 @@ Y_UNIT_TEST_SUITE(ProtobufSimpleReflection) { msg.AddRepStr("2"); msg.AddRepStr("3"); UNIT_ASSERT_VALUES_EQUAL(3, msg.RepStrSize()); // "1", "2", "3" - fld.Remove(0); // from begin + fld.Remove(0); // from begin UNIT_ASSERT_VALUES_EQUAL(2, msg.RepStrSize()); UNIT_ASSERT_VALUES_EQUAL("2", msg.GetRepStr(0)); UNIT_ASSERT_VALUES_EQUAL("3", msg.GetRepStr(1)); @@ -279,81 +279,81 @@ Y_UNIT_TEST_SUITE(ProtobufSimpleReflection) { // error { - {TSample msg; - UNIT_ASSERT(!TConstField::ByPath(msg, "SomeField")); + {TSample msg; + UNIT_ASSERT(!TConstField::ByPath(msg, "SomeField")); + } + + { + TSample msg; + UNIT_ASSERT(!TMutableField::ByPath(msg, "SomeField/FieldSome")); + } + + { + TSample msg; + UNIT_ASSERT(!TMutableField::ByPath(msg, "SomeField/FieldSome", true)); + } +} + +// extension +{ + TSample msg; + msg.SetExtension(NExt::TTestExt::ExtField, "ext"); + msg.SetExtension(NExt::ExtField, 2); + msg.AddExtension(NExt::Ext2Field, 33); + TInnerSample* subMsg = msg.MutableExtension(NExt::SubMsgExt); + subMsg->AddRepInt(20); + subMsg->SetExtension(NExt::Ext3Field, 54); + + { + TMaybe<TConstField> field = TConstField::ByPath(msg, "NExt.TTestExt.ExtField"); + UNIT_ASSERT(field); + UNIT_ASSERT(field->HasValue()); + UNIT_ASSERT_VALUES_EQUAL("ext", field->Get<TString>()); } - - { - TSample msg; - UNIT_ASSERT(!TMutableField::ByPath(msg, "SomeField/FieldSome")); - } - - { - TSample msg; - UNIT_ASSERT(!TMutableField::ByPath(msg, "SomeField/FieldSome", true)); - } -} - -// extension -{ - TSample msg; - msg.SetExtension(NExt::TTestExt::ExtField, "ext"); - msg.SetExtension(NExt::ExtField, 2); - msg.AddExtension(NExt::Ext2Field, 33); - TInnerSample* subMsg = msg.MutableExtension(NExt::SubMsgExt); - subMsg->AddRepInt(20); - subMsg->SetExtension(NExt::Ext3Field, 54); - - { - TMaybe<TConstField> field = TConstField::ByPath(msg, "NExt.TTestExt.ExtField"); - UNIT_ASSERT(field); - UNIT_ASSERT(field->HasValue()); - UNIT_ASSERT_VALUES_EQUAL("ext", field->Get<TString>()); - } - { - TMaybe<TConstField> field = TConstField::ByPath(msg, "NExt.ExtField"); - UNIT_ASSERT(field); - UNIT_ASSERT(field->HasValue()); - UNIT_ASSERT_VALUES_EQUAL(2, field->Get<int>()); - } - { - TMaybe<TConstField> field = TConstField::ByPath(msg, "ExtField"); // ambiguity - UNIT_ASSERT(!field); - } - { - TMaybe<TConstField> field = TConstField::ByPath(msg, "NExt.Ext2Field"); - UNIT_ASSERT(field); - UNIT_ASSERT(field->HasValue()); - UNIT_ASSERT_VALUES_EQUAL(33, field->Get<int>()); - } - { - TMaybe<TConstField> field = TConstField::ByPath(msg, "Ext2Field"); - UNIT_ASSERT(field); - UNIT_ASSERT(field->HasValue()); - UNIT_ASSERT_VALUES_EQUAL(33, field->Get<int>()); - } - { - TMaybe<TConstField> field = TConstField::ByPath(msg, "SubMsgExt"); - UNIT_ASSERT(field); - UNIT_ASSERT(field->HasValue()); - const TInnerSample* subMsg2 = field->GetAs<TInnerSample>(); - UNIT_ASSERT(subMsg2); - UNIT_ASSERT_VALUES_EQUAL(1, subMsg2->RepIntSize()); - UNIT_ASSERT_VALUES_EQUAL(20, subMsg2->GetRepInt(0)); - UNIT_ASSERT_VALUES_EQUAL(54, subMsg2->GetExtension(NExt::Ext3Field)); - } - { - TMaybe<TConstField> field = TConstField::ByPath(msg, "SubMsgExt/Ext3Field"); - UNIT_ASSERT(field); - UNIT_ASSERT(field->HasValue()); - UNIT_ASSERT_VALUES_EQUAL(54, field->Get<int>()); - } - { - TMaybe<TConstField> field = TConstField::ByPath(msg, "SubMsgExt/RepInt"); - UNIT_ASSERT(field); - UNIT_ASSERT(field->HasValue()); - UNIT_ASSERT_VALUES_EQUAL(20, field->Get<int>()); - } -} -} + { + TMaybe<TConstField> field = TConstField::ByPath(msg, "NExt.ExtField"); + UNIT_ASSERT(field); + UNIT_ASSERT(field->HasValue()); + UNIT_ASSERT_VALUES_EQUAL(2, field->Get<int>()); + } + { + TMaybe<TConstField> field = TConstField::ByPath(msg, "ExtField"); // ambiguity + UNIT_ASSERT(!field); + } + { + TMaybe<TConstField> field = TConstField::ByPath(msg, "NExt.Ext2Field"); + UNIT_ASSERT(field); + UNIT_ASSERT(field->HasValue()); + UNIT_ASSERT_VALUES_EQUAL(33, field->Get<int>()); + } + { + TMaybe<TConstField> field = TConstField::ByPath(msg, "Ext2Field"); + UNIT_ASSERT(field); + UNIT_ASSERT(field->HasValue()); + UNIT_ASSERT_VALUES_EQUAL(33, field->Get<int>()); + } + { + TMaybe<TConstField> field = TConstField::ByPath(msg, "SubMsgExt"); + UNIT_ASSERT(field); + UNIT_ASSERT(field->HasValue()); + const TInnerSample* subMsg2 = field->GetAs<TInnerSample>(); + UNIT_ASSERT(subMsg2); + UNIT_ASSERT_VALUES_EQUAL(1, subMsg2->RepIntSize()); + UNIT_ASSERT_VALUES_EQUAL(20, subMsg2->GetRepInt(0)); + UNIT_ASSERT_VALUES_EQUAL(54, subMsg2->GetExtension(NExt::Ext3Field)); + } + { + TMaybe<TConstField> field = TConstField::ByPath(msg, "SubMsgExt/Ext3Field"); + UNIT_ASSERT(field); + UNIT_ASSERT(field->HasValue()); + UNIT_ASSERT_VALUES_EQUAL(54, field->Get<int>()); + } + { + TMaybe<TConstField> field = TConstField::ByPath(msg, "SubMsgExt/RepInt"); + UNIT_ASSERT(field); + UNIT_ASSERT(field->HasValue()); + UNIT_ASSERT_VALUES_EQUAL(20, field->Get<int>()); + } } +} +} diff --git a/library/cpp/protobuf/util/sort.h b/library/cpp/protobuf/util/sort.h index 985ba6f689..5c9ed37161 100644 --- a/library/cpp/protobuf/util/sort.h +++ b/library/cpp/protobuf/util/sort.h @@ -6,23 +6,23 @@ #include <util/generic/algorithm.h> namespace NProtoBuf { - // TComparePtr is something like: - // typedef bool (*TComparePtr)(const Message* msg1, const Message* msg2); - // typedef bool (*TComparePtr)(const TProto* msg1, const TProto* msg2); + // TComparePtr is something like: + // typedef bool (*TComparePtr)(const Message* msg1, const Message* msg2); + // typedef bool (*TComparePtr)(const TProto* msg1, const TProto* msg2); - template <typename TProto, typename TComparePtr> - void SortMessages(RepeatedPtrField<TProto>& msgs, TComparePtr cmp) { - TVector<TProto*> ptrs; - ptrs.reserve(msgs.size()); - while (msgs.size()) { - ptrs.push_back(msgs.ReleaseLast()); - } + template <typename TProto, typename TComparePtr> + void SortMessages(RepeatedPtrField<TProto>& msgs, TComparePtr cmp) { + TVector<TProto*> ptrs; + ptrs.reserve(msgs.size()); + while (msgs.size()) { + ptrs.push_back(msgs.ReleaseLast()); + } - ::StableSort(ptrs.begin(), ptrs.end(), cmp); - - for (size_t i = 0; i < ptrs.size(); ++i) { - msgs.AddAllocated(ptrs[i]); - } + ::StableSort(ptrs.begin(), ptrs.end(), cmp); + + for (size_t i = 0; i < ptrs.size(); ++i) { + msgs.AddAllocated(ptrs[i]); + } } } diff --git a/library/cpp/protobuf/util/traits.h b/library/cpp/protobuf/util/traits.h index 50f036d0ea..8f00b6d6e1 100644 --- a/library/cpp/protobuf/util/traits.h +++ b/library/cpp/protobuf/util/traits.h @@ -11,302 +11,302 @@ namespace NProtoBuf { #undef GetMessage #endif - struct TCppTypeTraitsBase { - static inline bool Has(const Message& msg, const FieldDescriptor* field) { // non-repeated - return msg.GetReflection()->HasField(msg, field); - } - static inline size_t Size(const Message& msg, const FieldDescriptor* field) { // repeated - return msg.GetReflection()->FieldSize(msg, field); - } - - static inline void Clear(Message& msg, const FieldDescriptor* field) { - msg.GetReflection()->ClearField(&msg, field); - } - - static inline void RemoveLast(Message& msg, const FieldDescriptor* field) { - msg.GetReflection()->RemoveLast(&msg, field); - } - - static inline void SwapElements(Message& msg, const FieldDescriptor* field, int index1, int index2) { - msg.GetReflection()->SwapElements(&msg, field, index1, index2); - } + struct TCppTypeTraitsBase { + static inline bool Has(const Message& msg, const FieldDescriptor* field) { // non-repeated + return msg.GetReflection()->HasField(msg, field); + } + static inline size_t Size(const Message& msg, const FieldDescriptor* field) { // repeated + return msg.GetReflection()->FieldSize(msg, field); + } + + static inline void Clear(Message& msg, const FieldDescriptor* field) { + msg.GetReflection()->ClearField(&msg, field); + } + + static inline void RemoveLast(Message& msg, const FieldDescriptor* field) { + msg.GetReflection()->RemoveLast(&msg, field); + } + + static inline void SwapElements(Message& msg, const FieldDescriptor* field, int index1, int index2) { + msg.GetReflection()->SwapElements(&msg, field, index1, index2); + } + }; + + // default value accessor + template <FieldDescriptor::CppType cpptype> + struct TCppTypeTraitsDefault; + +#define DECLARE_CPPTYPE_DEFAULT(cpptype, method) \ + template <> \ + struct TCppTypeTraitsDefault<cpptype> { \ + static auto GetDefault(const FieldDescriptor* fd) \ + -> decltype(fd->default_value_##method()) { \ + Y_ASSERT(fd); \ + return fd->default_value_##method(); \ + } \ }; - // default value accessor - template <FieldDescriptor::CppType cpptype> - struct TCppTypeTraitsDefault; - -#define DECLARE_CPPTYPE_DEFAULT(cpptype, method) \ - template <> \ - struct TCppTypeTraitsDefault<cpptype> { \ - static auto GetDefault(const FieldDescriptor* fd) \ - -> decltype(fd->default_value_##method()) { \ - Y_ASSERT(fd); \ - return fd->default_value_##method(); \ - } \ - }; - - DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_INT32, int32); - DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_INT64, int64); - DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_UINT32, uint32); - DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_UINT64, uint64); - DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_FLOAT, float); - DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_DOUBLE, double); - DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_BOOL, bool); - DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_ENUM, enum); - DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_STRING, string); + DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_INT32, int32); + DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_INT64, int64); + DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_UINT32, uint32); + DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_UINT64, uint64); + DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_FLOAT, float); + DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_DOUBLE, double); + DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_BOOL, bool); + DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_ENUM, enum); + DECLARE_CPPTYPE_DEFAULT(FieldDescriptor::CppType::CPPTYPE_STRING, string); #undef DECLARE_CPPTYPE_DEFAULT - // getters/setters of field with specified CppType - template <FieldDescriptor::CppType cpptype> - struct TCppTypeTraits : TCppTypeTraitsBase { - static const FieldDescriptor::CppType CppType = cpptype; - - struct T {}; - static T Get(const Message& msg, const FieldDescriptor* field); - static T GetRepeated(const Message& msg, const FieldDescriptor* field, int index); - static T GetDefault(const FieldDescriptor* field); - - static void Set(Message& msg, const FieldDescriptor* field, T value); - static void AddRepeated(Message& msg, const FieldDescriptor* field, T value); - static void SetRepeated(Message& msg, const FieldDescriptor* field, int index, T value); + // getters/setters of field with specified CppType + template <FieldDescriptor::CppType cpptype> + struct TCppTypeTraits : TCppTypeTraitsBase { + static const FieldDescriptor::CppType CppType = cpptype; + + struct T {}; + static T Get(const Message& msg, const FieldDescriptor* field); + static T GetRepeated(const Message& msg, const FieldDescriptor* field, int index); + static T GetDefault(const FieldDescriptor* field); + + static void Set(Message& msg, const FieldDescriptor* field, T value); + static void AddRepeated(Message& msg, const FieldDescriptor* field, T value); + static void SetRepeated(Message& msg, const FieldDescriptor* field, int index, T value); + }; + + // any type T -> CppType + template <typename T> + struct TSelectCppType { + //static const FieldDescriptor::CppType Result = FieldDescriptor::MAX_CPPTYPE; + }; + +#define DECLARE_CPPTYPE_TRAITS(cpptype, type, method) \ + template <> \ + struct TCppTypeTraits<cpptype>: public TCppTypeTraitsBase { \ + typedef type T; \ + static const FieldDescriptor::CppType CppType = cpptype; \ + \ + static inline T Get(const Message& msg, const FieldDescriptor* field) { \ + return msg.GetReflection()->Get##method(msg, field); \ + } \ + static inline T GetRepeated(const Message& msg, const FieldDescriptor* field, int index) { \ + return msg.GetReflection()->GetRepeated##method(msg, field, index); \ + } \ + static inline T GetDefault(const FieldDescriptor* field) { \ + return TCppTypeTraitsDefault<cpptype>::GetDefault(field); \ + } \ + static inline void Set(Message& msg, const FieldDescriptor* field, T value) { \ + msg.GetReflection()->Set##method(&msg, field, value); \ + } \ + static inline void AddRepeated(Message& msg, const FieldDescriptor* field, T value) { \ + msg.GetReflection()->Add##method(&msg, field, value); \ + } \ + static inline void SetRepeated(Message& msg, const FieldDescriptor* field, int index, T value) { \ + msg.GetReflection()->SetRepeated##method(&msg, field, index, value); \ + } \ + }; \ + template <> \ + struct TSelectCppType<type> { \ + static const FieldDescriptor::CppType Result = cpptype; \ + typedef type T; \ }; - // any type T -> CppType - template <typename T> - struct TSelectCppType { - //static const FieldDescriptor::CppType Result = FieldDescriptor::MAX_CPPTYPE; - }; - -#define DECLARE_CPPTYPE_TRAITS(cpptype, type, method) \ - template <> \ - struct TCppTypeTraits<cpptype>: public TCppTypeTraitsBase { \ - typedef type T; \ - static const FieldDescriptor::CppType CppType = cpptype; \ - \ - static inline T Get(const Message& msg, const FieldDescriptor* field) { \ - return msg.GetReflection()->Get##method(msg, field); \ - } \ - static inline T GetRepeated(const Message& msg, const FieldDescriptor* field, int index) { \ - return msg.GetReflection()->GetRepeated##method(msg, field, index); \ - } \ - static inline T GetDefault(const FieldDescriptor* field) { \ - return TCppTypeTraitsDefault<cpptype>::GetDefault(field); \ - } \ - static inline void Set(Message& msg, const FieldDescriptor* field, T value) { \ - msg.GetReflection()->Set##method(&msg, field, value); \ - } \ - static inline void AddRepeated(Message& msg, const FieldDescriptor* field, T value) { \ - msg.GetReflection()->Add##method(&msg, field, value); \ - } \ - static inline void SetRepeated(Message& msg, const FieldDescriptor* field, int index, T value) { \ - msg.GetReflection()->SetRepeated##method(&msg, field, index, value); \ - } \ - }; \ - template <> \ - struct TSelectCppType<type> { \ - static const FieldDescriptor::CppType Result = cpptype; \ - typedef type T; \ - }; - - DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_INT32, i32, Int32); - DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_INT64, i64, Int64); - DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_UINT32, ui32, UInt32); - DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_UINT64, ui64, UInt64); - DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_DOUBLE, double, Double); - DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_FLOAT, float, Float); - DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_BOOL, bool, Bool); - DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_ENUM, const EnumValueDescriptor*, Enum); - DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_STRING, TString, String); - //DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_MESSAGE, const Message&, Message); + DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_INT32, i32, Int32); + DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_INT64, i64, Int64); + DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_UINT32, ui32, UInt32); + DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_UINT64, ui64, UInt64); + DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_DOUBLE, double, Double); + DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_FLOAT, float, Float); + DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_BOOL, bool, Bool); + DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_ENUM, const EnumValueDescriptor*, Enum); + DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_STRING, TString, String); + //DECLARE_CPPTYPE_TRAITS(FieldDescriptor::CPPTYPE_MESSAGE, const Message&, Message); #undef DECLARE_CPPTYPE_TRAITS - // specialization for message pointer - template <> - struct TCppTypeTraits<FieldDescriptor::CPPTYPE_MESSAGE>: public TCppTypeTraitsBase { - typedef const Message* T; - static const FieldDescriptor::CppType CppType = FieldDescriptor::CPPTYPE_MESSAGE; - - static inline T Get(const Message& msg, const FieldDescriptor* field) { - return &(msg.GetReflection()->GetMessage(msg, field)); - } - static inline T GetRepeated(const Message& msg, const FieldDescriptor* field, int index) { - return &(msg.GetReflection()->GetRepeatedMessage(msg, field, index)); - } - static inline Message* Set(Message& msg, const FieldDescriptor* field, const Message* value) { - Message* ret = msg.GetReflection()->MutableMessage(&msg, field); - ret->CopyFrom(*value); - return ret; - } - static inline Message* AddRepeated(Message& msg, const FieldDescriptor* field, const Message* value) { - Message* ret = msg.GetReflection()->AddMessage(&msg, field); - ret->CopyFrom(*value); - return ret; - } - static inline Message* SetRepeated(Message& msg, const FieldDescriptor* field, int index, const Message* value) { - Message* ret = msg.GetReflection()->MutableRepeatedMessage(&msg, field, index); - ret->CopyFrom(*value); - return ret; - } - }; - - template <> - struct TSelectCppType<const Message*> { - static const FieldDescriptor::CppType Result = FieldDescriptor::CPPTYPE_MESSAGE; - typedef const Message* T; - }; - - template <> - struct TSelectCppType<Message> { - static const FieldDescriptor::CppType Result = FieldDescriptor::CPPTYPE_MESSAGE; - typedef const Message* T; - }; - - template <FieldDescriptor::CppType CppType, bool Repeated> - struct TFieldTraits { - typedef TCppTypeTraits<CppType> TBaseTraits; - typedef typename TBaseTraits::T T; - - static inline T Get(const Message& msg, const FieldDescriptor* field, size_t index = 0) { - Y_ASSERT(index == 0); - return TBaseTraits::Get(msg, field); - } - - static inline T GetDefault(const FieldDescriptor* field) { - return TBaseTraits::GetDefault(field); - } - - static inline bool Has(const Message& msg, const FieldDescriptor* field) { - return TBaseTraits::Has(msg, field); - } - - static inline size_t Size(const Message& msg, const FieldDescriptor* field) { - return Has(msg, field); - } - - static inline void Set(Message& msg, const FieldDescriptor* field, T value, size_t index = 0) { - Y_ASSERT(index == 0); - TBaseTraits::Set(msg, field, value); - } - - static inline void Add(Message& msg, const FieldDescriptor* field, T value) { - TBaseTraits::Set(msg, field, value); - } - }; - - template <FieldDescriptor::CppType CppType> - struct TFieldTraits<CppType, true> { - typedef TCppTypeTraits<CppType> TBaseTraits; - typedef typename TBaseTraits::T T; - - static inline T Get(const Message& msg, const FieldDescriptor* field, size_t index = 0) { - return TBaseTraits::GetRepeated(msg, field, index); - } - - static inline T GetDefault(const FieldDescriptor* field) { - return TBaseTraits::GetDefault(field); - } - - static inline size_t Size(const Message& msg, const FieldDescriptor* field) { - return TBaseTraits::Size(msg, field); - } - - static inline bool Has(const Message& msg, const FieldDescriptor* field) { - return Size(msg, field) > 0; - } - - static inline void Set(Message& msg, const FieldDescriptor* field, T value, size_t index = 0) { - TBaseTraits::SetRepeated(msg, field, index, value); - } - - static inline void Add(Message& msg, const FieldDescriptor* field, T value) { - TBaseTraits::AddRepeated(msg, field, value); - } - }; - - // Simpler interface at the cost of checking is_repeated() on each call - template <FieldDescriptor::CppType CppType> - struct TSimpleFieldTraits { - typedef TFieldTraits<CppType, true> TRepeated; - typedef TFieldTraits<CppType, false> TSingle; - typedef typename TRepeated::T T; - - static inline size_t Size(const Message& msg, const FieldDescriptor* field) { - if (field->is_repeated()) - return TRepeated::Size(msg, field); - else - return TSingle::Size(msg, field); - } - - static inline bool Has(const Message& msg, const FieldDescriptor* field) { - if (field->is_repeated()) - return TRepeated::Has(msg, field); - else - return TSingle::Has(msg, field); - } - - static inline T Get(const Message& msg, const FieldDescriptor* field, size_t index = 0) { - Y_ASSERT(index < Size(msg, field) || !field->is_repeated() && index == 0); // Get for single fields is always allowed because of default values - if (field->is_repeated()) - return TRepeated::Get(msg, field, index); - else - return TSingle::Get(msg, field, index); - } - - static inline T GetDefault(const FieldDescriptor* field) { - return TSingle::GetDefault(field); - } - - static inline void Set(Message& msg, const FieldDescriptor* field, T value, size_t index = 0) { - Y_ASSERT(!field->is_repeated() && index == 0 || index < Size(msg, field)); - if (field->is_repeated()) - TRepeated::Set(msg, field, value, index); - else - TSingle::Set(msg, field, value, index); - } - - static inline void Add(Message& msg, const FieldDescriptor* field, T value) { - if (field->is_repeated()) - TRepeated::Add(msg, field, value); - else - TSingle::Add(msg, field, value); - } - }; - - // some cpp-type groups - - template <FieldDescriptor::CppType CppType> - struct TIsIntegerCppType { - enum { - Result = CppType == FieldDescriptor::CPPTYPE_INT32 || - CppType == FieldDescriptor::CPPTYPE_INT64 || - CppType == FieldDescriptor::CPPTYPE_UINT32 || - CppType == FieldDescriptor::CPPTYPE_UINT64 - }; + // specialization for message pointer + template <> + struct TCppTypeTraits<FieldDescriptor::CPPTYPE_MESSAGE>: public TCppTypeTraitsBase { + typedef const Message* T; + static const FieldDescriptor::CppType CppType = FieldDescriptor::CPPTYPE_MESSAGE; + + static inline T Get(const Message& msg, const FieldDescriptor* field) { + return &(msg.GetReflection()->GetMessage(msg, field)); + } + static inline T GetRepeated(const Message& msg, const FieldDescriptor* field, int index) { + return &(msg.GetReflection()->GetRepeatedMessage(msg, field, index)); + } + static inline Message* Set(Message& msg, const FieldDescriptor* field, const Message* value) { + Message* ret = msg.GetReflection()->MutableMessage(&msg, field); + ret->CopyFrom(*value); + return ret; + } + static inline Message* AddRepeated(Message& msg, const FieldDescriptor* field, const Message* value) { + Message* ret = msg.GetReflection()->AddMessage(&msg, field); + ret->CopyFrom(*value); + return ret; + } + static inline Message* SetRepeated(Message& msg, const FieldDescriptor* field, int index, const Message* value) { + Message* ret = msg.GetReflection()->MutableRepeatedMessage(&msg, field, index); + ret->CopyFrom(*value); + return ret; + } + }; + + template <> + struct TSelectCppType<const Message*> { + static const FieldDescriptor::CppType Result = FieldDescriptor::CPPTYPE_MESSAGE; + typedef const Message* T; + }; + + template <> + struct TSelectCppType<Message> { + static const FieldDescriptor::CppType Result = FieldDescriptor::CPPTYPE_MESSAGE; + typedef const Message* T; + }; + + template <FieldDescriptor::CppType CppType, bool Repeated> + struct TFieldTraits { + typedef TCppTypeTraits<CppType> TBaseTraits; + typedef typename TBaseTraits::T T; + + static inline T Get(const Message& msg, const FieldDescriptor* field, size_t index = 0) { + Y_ASSERT(index == 0); + return TBaseTraits::Get(msg, field); + } + + static inline T GetDefault(const FieldDescriptor* field) { + return TBaseTraits::GetDefault(field); + } + + static inline bool Has(const Message& msg, const FieldDescriptor* field) { + return TBaseTraits::Has(msg, field); + } + + static inline size_t Size(const Message& msg, const FieldDescriptor* field) { + return Has(msg, field); + } + + static inline void Set(Message& msg, const FieldDescriptor* field, T value, size_t index = 0) { + Y_ASSERT(index == 0); + TBaseTraits::Set(msg, field, value); + } + + static inline void Add(Message& msg, const FieldDescriptor* field, T value) { + TBaseTraits::Set(msg, field, value); + } + }; + + template <FieldDescriptor::CppType CppType> + struct TFieldTraits<CppType, true> { + typedef TCppTypeTraits<CppType> TBaseTraits; + typedef typename TBaseTraits::T T; + + static inline T Get(const Message& msg, const FieldDescriptor* field, size_t index = 0) { + return TBaseTraits::GetRepeated(msg, field, index); + } + + static inline T GetDefault(const FieldDescriptor* field) { + return TBaseTraits::GetDefault(field); + } + + static inline size_t Size(const Message& msg, const FieldDescriptor* field) { + return TBaseTraits::Size(msg, field); + } + + static inline bool Has(const Message& msg, const FieldDescriptor* field) { + return Size(msg, field) > 0; + } + + static inline void Set(Message& msg, const FieldDescriptor* field, T value, size_t index = 0) { + TBaseTraits::SetRepeated(msg, field, index, value); + } + + static inline void Add(Message& msg, const FieldDescriptor* field, T value) { + TBaseTraits::AddRepeated(msg, field, value); + } + }; + + // Simpler interface at the cost of checking is_repeated() on each call + template <FieldDescriptor::CppType CppType> + struct TSimpleFieldTraits { + typedef TFieldTraits<CppType, true> TRepeated; + typedef TFieldTraits<CppType, false> TSingle; + typedef typename TRepeated::T T; + + static inline size_t Size(const Message& msg, const FieldDescriptor* field) { + if (field->is_repeated()) + return TRepeated::Size(msg, field); + else + return TSingle::Size(msg, field); + } + + static inline bool Has(const Message& msg, const FieldDescriptor* field) { + if (field->is_repeated()) + return TRepeated::Has(msg, field); + else + return TSingle::Has(msg, field); + } + + static inline T Get(const Message& msg, const FieldDescriptor* field, size_t index = 0) { + Y_ASSERT(index < Size(msg, field) || !field->is_repeated() && index == 0); // Get for single fields is always allowed because of default values + if (field->is_repeated()) + return TRepeated::Get(msg, field, index); + else + return TSingle::Get(msg, field, index); + } + + static inline T GetDefault(const FieldDescriptor* field) { + return TSingle::GetDefault(field); + } + + static inline void Set(Message& msg, const FieldDescriptor* field, T value, size_t index = 0) { + Y_ASSERT(!field->is_repeated() && index == 0 || index < Size(msg, field)); + if (field->is_repeated()) + TRepeated::Set(msg, field, value, index); + else + TSingle::Set(msg, field, value, index); + } + + static inline void Add(Message& msg, const FieldDescriptor* field, T value) { + if (field->is_repeated()) + TRepeated::Add(msg, field, value); + else + TSingle::Add(msg, field, value); + } + }; + + // some cpp-type groups + + template <FieldDescriptor::CppType CppType> + struct TIsIntegerCppType { + enum { + Result = CppType == FieldDescriptor::CPPTYPE_INT32 || + CppType == FieldDescriptor::CPPTYPE_INT64 || + CppType == FieldDescriptor::CPPTYPE_UINT32 || + CppType == FieldDescriptor::CPPTYPE_UINT64 + }; }; - template <FieldDescriptor::CppType CppType> - struct TIsFloatCppType { - enum { - Result = CppType == FieldDescriptor::CPPTYPE_FLOAT || - CppType == FieldDescriptor::CPPTYPE_DOUBLE - }; + template <FieldDescriptor::CppType CppType> + struct TIsFloatCppType { + enum { + Result = CppType == FieldDescriptor::CPPTYPE_FLOAT || + CppType == FieldDescriptor::CPPTYPE_DOUBLE + }; }; - template <FieldDescriptor::CppType CppType> - struct TIsNumericCppType { - enum { - Result = CppType == FieldDescriptor::CPPTYPE_BOOL || - TIsIntegerCppType<CppType>::Result || - TIsFloatCppType<CppType>::Result - }; + template <FieldDescriptor::CppType CppType> + struct TIsNumericCppType { + enum { + Result = CppType == FieldDescriptor::CPPTYPE_BOOL || + TIsIntegerCppType<CppType>::Result || + TIsFloatCppType<CppType>::Result + }; }; - // a helper macro for splitting flow by cpp-type (e.g. in a switch) + // a helper macro for splitting flow by cpp-type (e.g. in a switch) -#define APPLY_TMP_MACRO_FOR_ALL_CPPTYPES() \ +#define APPLY_TMP_MACRO_FOR_ALL_CPPTYPES() \ TMP_MACRO_FOR_CPPTYPE(NProtoBuf::FieldDescriptor::CPPTYPE_INT32) \ TMP_MACRO_FOR_CPPTYPE(NProtoBuf::FieldDescriptor::CPPTYPE_INT64) \ TMP_MACRO_FOR_CPPTYPE(NProtoBuf::FieldDescriptor::CPPTYPE_UINT32) \ @@ -317,4 +317,4 @@ namespace NProtoBuf { TMP_MACRO_FOR_CPPTYPE(NProtoBuf::FieldDescriptor::CPPTYPE_ENUM) \ TMP_MACRO_FOR_CPPTYPE(NProtoBuf::FieldDescriptor::CPPTYPE_STRING) \ TMP_MACRO_FOR_CPPTYPE(NProtoBuf::FieldDescriptor::CPPTYPE_MESSAGE) -} +} diff --git a/library/cpp/protobuf/util/walk.h b/library/cpp/protobuf/util/walk.h index d15d76562d..d5d40eee69 100644 --- a/library/cpp/protobuf/util/walk.h +++ b/library/cpp/protobuf/util/walk.h @@ -8,9 +8,9 @@ #include <functional> namespace NProtoBuf { - // Apply @onField processor to each field in @msg (even empty) + // Apply @onField processor to each field in @msg (even empty) // Do not walk deeper the field if the field is an empty message - // Returned bool defines if we should walk down deeper to current node children (true), or not (false) + // Returned bool defines if we should walk down deeper to current node children (true), or not (false) void WalkReflection(Message& msg, std::function<bool(Message&, const FieldDescriptor*)> onField); void WalkReflection(const Message& msg, diff --git a/library/cpp/protobuf/util/walk_ut.cpp b/library/cpp/protobuf/util/walk_ut.cpp index 2ea6071b17..2b101e79c5 100644 --- a/library/cpp/protobuf/util/walk_ut.cpp +++ b/library/cpp/protobuf/util/walk_ut.cpp @@ -7,7 +7,7 @@ using namespace NProtoBuf; Y_UNIT_TEST_SUITE(ProtobufWalk) { - static void InitProto(NProtobufUtilUt::TWalkTest & p, int level = 0) { + static void InitProto(NProtobufUtilUt::TWalkTest & p, int level = 0) { p.SetOptInt(1); p.AddRepInt(2); p.AddRepInt(3); @@ -24,16 +24,16 @@ Y_UNIT_TEST_SUITE(ProtobufWalk) { } } - static bool IncreaseInts(Message & msg, const FieldDescriptor* fd) { + static bool IncreaseInts(Message & msg, const FieldDescriptor* fd) { TMutableField f(msg, fd); if (f.IsInstance<ui32>()) { for (size_t i = 0; i < f.Size(); ++i) - f.Set(f.Get<ui64>(i) + 1, i); // ui64 should be ok! + f.Set(f.Get<ui64>(i) + 1, i); // ui64 should be ok! } return true; } - static bool RepeatString1(Message & msg, const FieldDescriptor* fd) { + static bool RepeatString1(Message & msg, const FieldDescriptor* fd) { TMutableField f(msg, fd); if (f.IsString()) { for (size_t i = 0; i < f.Size(); ++i) @@ -43,7 +43,7 @@ Y_UNIT_TEST_SUITE(ProtobufWalk) { return true; } - static bool ClearXXX(Message & msg, const FieldDescriptor* fd) { + static bool ClearXXX(Message & msg, const FieldDescriptor* fd) { const FieldOptions& opt = fd->options(); if (opt.HasExtension(NProtobufUtilUt::XXX) && opt.GetExtension(NProtobufUtilUt::XXX)) TMutableField(msg, fd).Clear(); diff --git a/library/cpp/protobuf/util/ya.make b/library/cpp/protobuf/util/ya.make index b62028af58..6c9410ee77 100644 --- a/library/cpp/protobuf/util/ya.make +++ b/library/cpp/protobuf/util/ya.make @@ -1,4 +1,4 @@ -LIBRARY() +LIBRARY() OWNER(mowgli) |