diff --git a/.github/workflows/test_cpp.yml b/.github/workflows/test_cpp.yml index 82d71fb0b1..9dc1f50619 100644 --- a/.github/workflows/test_cpp.yml +++ b/.github/workflows/test_cpp.yml @@ -80,7 +80,6 @@ jobs: with: image: us-docker.pkg.dev/protobuf-build/containers/test/linux/emulation:${{ matrix.arch }}-3af05275178e16af30961976af126eabbbb2c733 credentials: ${{ secrets.GAR_SERVICE_ACCOUNT }} - skip-staleness-check: true entrypoint: bash command: > -c "set -ex; diff --git a/objectivec/GPBType.pbobjc.h b/objectivec/GPBType.pbobjc.h index 35a03f9203..28638fa086 100644 --- a/objectivec/GPBType.pbobjc.h +++ b/objectivec/GPBType.pbobjc.h @@ -43,6 +43,9 @@ typedef GPB_ENUM(GPBSyntax) { /** Syntax `proto3`. */ GPBSyntax_SyntaxProto3 = 1, + + /** Syntax `editions`. */ + GPBSyntax_SyntaxEditions = 2, }; GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void); @@ -184,6 +187,7 @@ typedef GPB_ENUM(GPBType_FieldNumber) { GPBType_FieldNumber_OptionsArray = 4, GPBType_FieldNumber_SourceContext = 5, GPBType_FieldNumber_Syntax = 6, + GPBType_FieldNumber_Edition = 7, }; /** @@ -217,6 +221,9 @@ GPB_FINAL @interface GPBType : GPBMessage /** The source syntax. */ @property(nonatomic, readwrite) GPBSyntax syntax; +/** The source edition string, only valid when syntax is SYNTAX_EDITIONS. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *edition; + @end /** @@ -323,6 +330,7 @@ typedef GPB_ENUM(GPBEnum_FieldNumber) { GPBEnum_FieldNumber_OptionsArray = 3, GPBEnum_FieldNumber_SourceContext = 4, GPBEnum_FieldNumber_Syntax = 5, + GPBEnum_FieldNumber_Edition = 6, }; /** @@ -351,6 +359,9 @@ GPB_FINAL @interface GPBEnum : GPBMessage /** The source syntax. */ @property(nonatomic, readwrite) GPBSyntax syntax; +/** The source edition string, only valid when syntax is SYNTAX_EDITIONS. */ +@property(nonatomic, readwrite, copy, null_resettable) NSString *edition; + @end /** diff --git a/objectivec/GPBType.pbobjc.m b/objectivec/GPBType.pbobjc.m index 04e262c574..db7a41f7e5 100644 --- a/objectivec/GPBType.pbobjc.m +++ b/objectivec/GPBType.pbobjc.m @@ -54,10 +54,12 @@ GPBEnumDescriptor *GPBSyntax_EnumDescriptor(void) { if (!descriptor) { GPB_DEBUG_CHECK_RUNTIME_VERSIONS(); static const char *valueNames = - "SyntaxProto2\000SyntaxProto3\000"; + "SyntaxProto2\000SyntaxProto3\000SyntaxEditions" + "\000"; static const int32_t values[] = { GPBSyntax_SyntaxProto2, GPBSyntax_SyntaxProto3, + GPBSyntax_SyntaxEditions, }; GPBEnumDescriptor *worker = [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBSyntax) @@ -78,6 +80,7 @@ BOOL GPBSyntax_IsValidValue(int32_t value__) { switch (value__) { case GPBSyntax_SyntaxProto2: case GPBSyntax_SyntaxProto3: + case GPBSyntax_SyntaxEditions: return YES; default: return NO; @@ -212,6 +215,7 @@ BOOL GPBField_Cardinality_IsValidValue(int32_t value__) { @dynamic optionsArray, optionsArray_Count; @dynamic hasSourceContext, sourceContext; @dynamic syntax; +@dynamic edition; typedef struct GPBType__storage_ { uint32_t _has_storage_[1]; @@ -221,6 +225,7 @@ typedef struct GPBType__storage_ { NSMutableArray *oneofsArray; NSMutableArray *optionsArray; GPBSourceContext *sourceContext; + NSString *edition; } GPBType__storage_; // This method is threadsafe because it is initially called @@ -284,6 +289,15 @@ typedef struct GPBType__storage_ { .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeEnum, }, + { + .name = "edition", + .dataTypeSpecific.clazz = Nil, + .number = GPBType_FieldNumber_Edition, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GPBType__storage_, edition), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, }; GPBDescriptor *localDescriptor = [GPBDescriptor allocDescriptorForClass:GPBObjCClass(GPBType) @@ -497,6 +511,7 @@ void SetGPBField_Cardinality_RawValue(GPBField *message, int32_t value) { @dynamic optionsArray, optionsArray_Count; @dynamic hasSourceContext, sourceContext; @dynamic syntax; +@dynamic edition; typedef struct GPBEnum__storage_ { uint32_t _has_storage_[1]; @@ -505,6 +520,7 @@ typedef struct GPBEnum__storage_ { NSMutableArray *enumvalueArray; NSMutableArray *optionsArray; GPBSourceContext *sourceContext; + NSString *edition; } GPBEnum__storage_; // This method is threadsafe because it is initially called @@ -559,6 +575,15 @@ typedef struct GPBEnum__storage_ { .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldHasEnumDescriptor | GPBFieldClearHasIvarOnZero), .dataType = GPBDataTypeEnum, }, + { + .name = "edition", + .dataTypeSpecific.clazz = Nil, + .number = GPBEnum_FieldNumber_Edition, + .hasIndex = 3, + .offset = (uint32_t)offsetof(GPBEnum__storage_, edition), + .flags = (GPBFieldFlags)(GPBFieldOptional | GPBFieldClearHasIvarOnZero), + .dataType = GPBDataTypeString, + }, }; GPBDescriptor *localDescriptor = [GPBDescriptor allocDescriptorForClass:GPBObjCClass(GPBEnum) diff --git a/src/google/protobuf/type.proto b/src/google/protobuf/type.proto index fd25a41930..48cb11e755 100644 --- a/src/google/protobuf/type.proto +++ b/src/google/protobuf/type.proto @@ -57,6 +57,8 @@ message Type { SourceContext source_context = 5; // The source syntax. Syntax syntax = 6; + // The source edition string, only valid when syntax is SYNTAX_EDITIONS. + string edition = 7; } // A single field of a message type. @@ -151,6 +153,8 @@ message Enum { SourceContext source_context = 4; // The source syntax. Syntax syntax = 5; + // The source edition string, only valid when syntax is SYNTAX_EDITIONS. + string edition = 6; } // Enum value definition. @@ -184,4 +188,6 @@ enum Syntax { SYNTAX_PROTO2 = 0; // Syntax `proto3`. SYNTAX_PROTO3 = 1; + // Syntax `editions`. + SYNTAX_EDITIONS = 2; } diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc index 1537708986..e408e78b89 100644 --- a/src/google/protobuf/util/type_resolver_util.cc +++ b/src/google/protobuf/util/type_resolver_util.cc @@ -30,10 +30,13 @@ #include "google/protobuf/util/type_resolver_util.h" +#include +#include + +#include "google/protobuf/source_context.pb.h" #include "google/protobuf/type.pb.h" #include "google/protobuf/wrappers.pb.h" #include "google/protobuf/descriptor.pb.h" -#include "google/protobuf/descriptor.h" #include "absl/log/absl_log.h" #include "absl/status/status.h" #include "absl/strings/escaping.h" @@ -63,10 +66,255 @@ using google::protobuf::Int32Value; using google::protobuf::Int64Value; using google::protobuf::Option; using google::protobuf::StringValue; +using google::protobuf::Syntax; using google::protobuf::Type; using google::protobuf::UInt32Value; using google::protobuf::UInt64Value; +template +static WrapperT WrapValue(T value) { + WrapperT wrapper; + wrapper.set_value(value); + return wrapper; +} + +void ConvertOptionField(const Reflection* reflection, const Message& options, + const FieldDescriptor* field, int index, Option* out) { + out->set_name(field->is_extension() ? field->full_name() : field->name()); + Any* value = out->mutable_value(); + switch (field->cpp_type()) { + case FieldDescriptor::CPPTYPE_MESSAGE: + value->PackFrom( + field->is_repeated() + ? reflection->GetRepeatedMessage(options, field, index) + : reflection->GetMessage(options, field)); + return; + case FieldDescriptor::CPPTYPE_DOUBLE: + value->PackFrom(WrapValue( + field->is_repeated() + ? reflection->GetRepeatedDouble(options, field, index) + : reflection->GetDouble(options, field))); + return; + case FieldDescriptor::CPPTYPE_FLOAT: + value->PackFrom(WrapValue( + field->is_repeated() + ? reflection->GetRepeatedFloat(options, field, index) + : reflection->GetFloat(options, field))); + return; + case FieldDescriptor::CPPTYPE_INT64: + value->PackFrom(WrapValue( + field->is_repeated() + ? reflection->GetRepeatedInt64(options, field, index) + : reflection->GetInt64(options, field))); + return; + case FieldDescriptor::CPPTYPE_UINT64: + value->PackFrom(WrapValue( + field->is_repeated() + ? reflection->GetRepeatedUInt64(options, field, index) + : reflection->GetUInt64(options, field))); + return; + case FieldDescriptor::CPPTYPE_INT32: + value->PackFrom(WrapValue( + field->is_repeated() + ? reflection->GetRepeatedInt32(options, field, index) + : reflection->GetInt32(options, field))); + return; + case FieldDescriptor::CPPTYPE_UINT32: + value->PackFrom(WrapValue( + field->is_repeated() + ? reflection->GetRepeatedUInt32(options, field, index) + : reflection->GetUInt32(options, field))); + return; + case FieldDescriptor::CPPTYPE_BOOL: + value->PackFrom(WrapValue( + field->is_repeated() + ? reflection->GetRepeatedBool(options, field, index) + : reflection->GetBool(options, field))); + return; + case FieldDescriptor::CPPTYPE_STRING: { + const std::string& val = + field->is_repeated() + ? reflection->GetRepeatedString(options, field, index) + : reflection->GetString(options, field); + if (field->type() == FieldDescriptor::TYPE_STRING) { + value->PackFrom(WrapValue(val)); + } else { + value->PackFrom(WrapValue(val)); + } + return; + } + case FieldDescriptor::CPPTYPE_ENUM: { + const EnumValueDescriptor* val = + field->is_repeated() + ? reflection->GetRepeatedEnum(options, field, index) + : reflection->GetEnum(options, field); + value->PackFrom(WrapValue(val->number())); + return; + } + } +} + +// Implementation details for Convert*Options. +void ConvertOptionsInternal(const Message& options, + RepeatedPtrField