diff --git a/content/best-practices/1-1-1.md b/content/best-practices/1-1-1.md index 62462cc64..acf459733 100644 --- a/content/best-practices/1-1-1.md +++ b/content/best-practices/1-1-1.md @@ -42,7 +42,7 @@ edition = "2023"; package my.package; -message StudentID { +message StudentId { string value = 1; } ``` @@ -114,7 +114,7 @@ package my.package; import "student_id.proto"; message GetStudentRequest { - StudentID id = 1; + StudentId id = 1; } ``` @@ -154,17 +154,17 @@ The service definition and each of the message definitions are each in their own file, and you use includes to give access to the messages from other schema files. -In this example, `Student`, `StudentID`, and `FullName` are domain types that +In this example, `Student`, `StudentId`, and `FullName` are domain types that are reusable across requests and responses. The top-level request and response protos are unique to each service+method. If you later need to add a `middle_name` field to the `FullName` message, you won't need to update every individual top-level message with that new field. Likewise, if you need to update `Student` with more information, all the -requests and responses get the update. Further, `StudentID` might update to be a +requests and responses get the update. Further, `StudentId` might update to be a multi-part ID. -Lastly, having even simple types like `StudentID` wrapped as a message means +Lastly, having even simple types like `StudentId` wrapped as a message means that you have created a type that has semantics and consolidated documentation. For something like `FullName` you'll need to be careful with where this PII gets logged; this is another advantage of not repeating these fields in multiple diff --git a/content/editions/features.md b/content/editions/features.md index cec962d81..d9c80e6ab 100644 --- a/content/editions/features.md +++ b/content/editions/features.md @@ -590,6 +590,29 @@ message MyMessage { } ``` +#### `features.(pb.java).large_enum` {#java-large_enum} + +**Languages:** Java + +This language-specific feature enables you to adopt new functionality that +handles large enums in Java without causing compiler errors. + +This is new behavior, so doesn't affect proto2 or proto3 schema definition +files. + +**Values available:** + +* `true`: Java enums will use the new functionality. +* `false`: Java enums will continue to use Java enums. + +**Applicable to the following scopes:** Enum + +**Default behavior in Edition 2023:** `false` + +**Behavior in proto2:** `false` + +**Behavior in proto3:** `false` + ## Preserving proto2 or proto3 Behavior {#preserving} You may want to move to the editions format but not deal with updates to the way diff --git a/content/editions/overview.md b/content/editions/overview.md index ee46ea8ce..1be4756c6 100644 --- a/content/editions/overview.md +++ b/content/editions/overview.md @@ -271,11 +271,9 @@ as it applies the file-level setting. The `Employment` `enum`, though, will be ### Prototiller {#prototiller} -Currently, all conversions to editions format are handled by the Protobuf team. - -When this shifts to a self-serve model, we will provide both a migration guide -and migration tooling to ease the migration to and between editions. The tool, -called Prototiller, will enable you to: +When the Prototiller tool is launched, we will +provide both a migration guide and migration tooling to ease the migration to +and between editions. The tool will enable you to: * convert proto2 and proto3 definition files to the new editions syntax, at scale diff --git a/content/news/2024-12-04.md b/content/news/2024-12-04.md index 8679ee36c..927799b9e 100644 --- a/content/news/2024-12-04.md +++ b/content/news/2024-12-04.md @@ -6,7 +6,7 @@ description = "Changes announced for Protocol Buffers on December 4, 2024." type = "docs" +++ -We are planning to modify the Protobuf debug APIs (including Protobuf +We are planning to modify the Protobuf debug APIs for C++ (including Protobuf AbslStringify, `proto2::ShortFormat`, `proto2::Utf8Format`, `Message::DebugString`, `Message::ShortDebugString`, `Message::Utf8DebugString`) in v30 to redact sensitive fields annotated by `debug_redact`; the outputs of diff --git a/content/news/2025-01-23.md b/content/news/2025-01-23.md new file mode 100644 index 000000000..bd7832ef3 --- /dev/null +++ b/content/news/2025-01-23.md @@ -0,0 +1,38 @@ ++++ +title = "Changes announced January 23, 2025" +linkTitle = "January 23, 2025" +toc_hide = "true" +description = "Changes announced for Protocol Buffers on January 23, 2025." +type = "docs" ++++ + +## Poison Java gencode + +We are patching a change into the 25.x branch that will poison Java gencode that +was created prior to the +[3.21.7 release](https://github.com/protocolbuffers/protobuf/releases/tag/v21.7). +We will then mark all versions of Java protobuf from 3.21.7 through 3.25.5 as +vulnerable to the +[footmitten CVE](https://github.com/protocolbuffers/protobuf/security/advisories/GHSA-h4h5-3hr4-j3g2). + +After this change is patched in, protobuf will throw an +`UnsupportedOperationException` from the +[`makeExtensionsImmutable`](https://protobuf.dev/reference/java/api-docs/com/google/protobuf/GeneratedMessage.html#makeExtensionsImmutable\(\)) +method unless you set the system property +"`-Dcom.google.protobuf.use_unsafe_pre22_gencode`". Using this system property +can buy you some time if you can't update your code immediately, but should be +considered a short-term workaround. + +## Poison MSVC + Bazel + +We will be dropping support for using Bazel and MSVC together in v34. As of v30, +we will poison this combination with an error unless you specify the opt-out +flag `--define=protobuf_allow_msvc=true` to silence it. + +MSVC's path length limits combined with Bazel's sandboxing have become +increasingly difficult to support in combination. Rather than randomly break +users who install protobuf into a long path, we will prohibit the use of MSVC +from Bazel altogether. We will continue to support MSVC with CMake, and begin +supporting [clang-cl](https://clang.llvm.org/docs/UsersManual.html#clang-cl) +with Bazel. For any feedback or discussion, see +https://github.com/protocolbuffers/protobuf/issues/20085. diff --git a/content/news/_index.md b/content/news/_index.md index 3c63c5ced..e7e69f686 100644 --- a/content/news/_index.md +++ b/content/news/_index.md @@ -20,6 +20,8 @@ New news topics will also be published to the The following news topics provide information in the reverse order in which it was released. +* [January 23, 2025](/news/2025-01-23) - Poison Java + gencode * [December 18, 2024](/news/2024-12-18) - Go Protobuf: The new Opaque API * [December 13, 2024](/news/2024-12-13) - Removing diff --git a/content/news/v25.md b/content/news/v25.md index a59e5c035..d6471380f 100644 --- a/content/news/v25.md +++ b/content/news/v25.md @@ -45,3 +45,20 @@ same to minimize the need for additional changes, but there are two exceptions: - The top-level `BUILD` file for μpb has moved into the `upb` directory. So, for example, references to `@upb//:reflection` should now be written `@com_google_protobuf//upb:reflection`. + +## Poison Java gencode + +We are patching a change into the 25.x branch that will poison Java gencode that +was created prior to the +[3.21.7 release](https://github.com/protocolbuffers/protobuf/releases/tag/v21.7). +We will then mark all versions of Java protobuf from 3.21.7 through 3.25.5 as +vulnerable to the +[footmitten CVE](https://github.com/protocolbuffers/protobuf/security/advisories/GHSA-h4h5-3hr4-j3g2). + +After this change is patched in, protobuf will throw an +`UnsupportedOperationException` from the +[`makeExtensionsImmutable`](https://protobuf.dev/reference/java/api-docs/com/google/protobuf/GeneratedMessage.html#makeExtensionsImmutable\(\)) +method unless you set the system property +"`-Dcom.google.protobuf.use_unsafe_pre22_gencode`". Using this system property +can buy you some time if you can't update your code immediately, but should be +considered a short-term workaround. diff --git a/content/news/v30.md b/content/news/v30.md index 2f8d0ed43..17b235ca9 100644 --- a/content/news/v30.md +++ b/content/news/v30.md @@ -111,7 +111,7 @@ This release will drop C++ 14 as the minimum supported version and raise it to Per [our policies](https://protobuf.dev/support/version-support), we do not consider this to be a breaking change. -## Introduce ASAN Poisoning After Clearing Oneof Messages on Arena +### Introduce ASAN Poisoning After Clearing Oneof Messages on Arena This change adds a hardening check that affects C++ protobufs using Arenas. Oneof messages allocated on the protobuf arena will now be cleared in debug and @@ -120,7 +120,7 @@ region will cause a crash in ASAN as a use-after-free error. This implementation requires C++17. -## Dropping our C++ CocoaPods release +### Dropping our C++ CocoaPods release In v30, we will be dropping our C++ CocoaPods release, which has been broken since v4.x.x. C++ users should use our @@ -381,7 +381,23 @@ allocDescriptorForName:valueNames:values:count:enumVerifier:extraTextFormatInfo: **Replacement:** Regenerate with a current version of the library. -## Other Changes {#non-breaking} +## Other Changes {#other} + +### Poison MSVC + Bazel + +We will be dropping support for using Bazel and MSVC together in v34. As of v30, +we will poison this combination with an error unless you specify the opt-out +flag `--define=protobuf_allow_msvc=true` to silence it. + +MSVC's path length limits combined with Bazel's sandboxing have become +increasingly difficult to support in combination. Rather than randomly break +users who install protobuf into a long path, we will prohibit the use of MSVC +from Bazel altogether. We will continue to support MSVC with CMake, and begin +supporting [clang-cl](https://clang.llvm.org/docs/UsersManual.html#clang-cl) +with Bazel. For any feedback or discussion, see +https://github.com/protocolbuffers/protobuf/issues/20085. + +## Other Changes (Non-Breaking) {#non-breaking} In addition to those breaking changes are some other changes worth noting. While the following are not considered breaking changes, they may still impact users. @@ -399,7 +415,7 @@ v30 will includes a fix to make UTF-8 enforcement consistent across languages. Users with bad non-UTF8 data in string fields may see surfaced UTF-8 enforcement errors earlier. -## Ruby and PHP Errors in JSON Parsing +### Ruby and PHP Errors in JSON Parsing v30 fixes non-conformance in JSON parsing of strings in numeric fields per the [JSON spec](https://protobuf.dev/programming-guides/json/). diff --git a/content/overview.md b/content/overview.md index 3f34ec28d..6dc73dcf9 100644 --- a/content/overview.md +++ b/content/overview.md @@ -233,9 +233,7 @@ std::string email = john.email(); When defining `.proto` files, you can specify that a field is either `optional` or `repeated` (proto2 and proto3) or leave it set to the default, implicit presence, in proto3. (The option to set a field to `required` is absent in -proto3 and strongly discouraged in proto2. For more on this, see "Required is -Forever" in -[Specifying Field Rules](/programming-guides/proto3#specifying-field-rules).) +proto3 and strongly discouraged in proto2. For more on this, see [Required Fields Considered Harmful](/programming-guides/required-considered-harmful.md).) After setting the optionality/repeatability of a field, you specify the data type. Protocol buffers support the usual primitive data types, such as integers, diff --git a/content/programming-guides/deserialize-debug.md b/content/programming-guides/deserialize-debug.md index 26fe363cd..89c555099 100644 --- a/content/programming-guides/deserialize-debug.md +++ b/content/programming-guides/deserialize-debug.md @@ -23,7 +23,7 @@ and a randomized-length whitespace sequence. The new debugging format looks as follows: ```none -go/nodeserialize +goo.gle/nodeserialize spii_field: [REDACTED] normal_field: "value" ``` diff --git a/content/programming-guides/style.md b/content/programming-guides/style.md index a505c70d4..74f6e4190 100644 --- a/content/programming-guides/style.md +++ b/content/programming-guides/style.md @@ -9,12 +9,6 @@ This document provides a style guide for `.proto` files. By following these conventions, you'll make your protocol buffer message definitions and their corresponding classes consistent and easy to read. -Note that protocol buffer style has evolved over time, so it is likely that you -will see `.proto` files written in different conventions or styles. **Respect -the existing style** when you modify these files. **Consistency is key**. -However, it is best to adopt the current best style when you are creating a new -`.proto` file. - ## Standard File Formatting {#standard-file-formatting} * Keep the line length to 80 characters. @@ -35,60 +29,105 @@ All files should be ordered in the following manner: 1. File options 1. Everything else +## Identifier naming styles {#identifier} + +Protobuf identifiers use one of the following naming styles: + +1. TitleCase + * Contains uppercase letters, lowercase letters, and numbers + * The initial character is an uppercase letter + * The initial letter of each word is capitalized +1. lower_snake_case + * Contains lowercase letters, underscores, and numbers + * Words are separated by a single underscore +1. UPPER_SNAKE_CASE + * Contains uppercase letters, underscores, and numbers + * Words are separated by a single underscore +1. camelCase + * Contains uppercase letters, lowercase letters, and numbers + * The initial character is an lowercase letter + * The initial letter of each subsequent word is capitalized + * **Note:** The style guide below does not use camelCase for any + identifier in .proto files; the terminology is only clarified here since + some language's generated code may transform identifiers into this + style. + +In all cases, treat abbreviations as though they are single words: use +`GetDnsRequest` rather than `GetDNSRequest`, `dns_request` rather than +`d_n_s_request`. + +#### Underscores in Identifiers {#underscores} + +Don't use underscores as the initial or final character of a name. Any +underscore should always be followed by a letter (not a number or a second +underscore). + +The motivation for this rule is that each protobuf language implementation may +convert identifiers into the local language style: a name of `song_id` in a +.proto file may end up having accessors for the field which are capitalized as +as `SongId`, `songId` or `song_id` depending on the language. + +By using underscores only before letters, it avoids situations where names may +be distinct in one style, but would collide after they are transformed into one +of the other styles. + +For example, both `DNS2` and `DNS_2` would both transform into TitleCase as +`Dns2`. Allowing either of those names can be lead to painful situations when a +message is used only in some languages where the generated code keeps the +original UPPER_SNAKE_CASE style, becomes widely established, and then is only +later used in a language where names are transformed to TitleCase where they +collide. + +When applied, this style rule means that you should use `XYZ2` or `XYZ_V2` +rather than `XYZ_2`. + ## Packages {#packages} -Package names should be in lowercase. Package names should have unique names -based on the project name, and possibly based on the path of the file containing -the protocol buffer type definitions. +Use dot-delimited lower_snake_case names as package names. + +Multi-word package names may be lower_snake_case or dot.delimited (dot-delimited +package names are emitted as nested packages/namespaces in most languages). + +Package names should attempt to be a short but unique name based on the project +name. Package names should not be Java packages (`com.x.y`); instead use `x.y` +as the package and use the `java_package` option as needed. -## Message and Field Names {#message-field-names} +## Message Names {#message-names} -Use PascalCase (with an initial capital) for message names: `SongServerRequest`. -Prefer to capitalize abbreviations as single words: `GetDnsRequest` rather than -`GetDNSRequest`. Use lower_snake_case for field names, including oneof field and -extension names: `song_name`. +Use TitleCase for message names. ```proto -message SongServerRequest { - optional string song_name = 1; +message SongRequest { } ``` -Using this naming convention for field names gives you accessors like those -shown in the following two code samples. +## Field Names {#field-names} -C++: +Use snake_case for field names, including extensions. -```cpp -const string& song_name() { ... } -void set_song_name(const string& x) { ... } -``` - -Java: +Use pluralized names for repeated fields. -```java -public String getSongName() { ... } -public Builder setSongName(String v) { ... } +```proto +string song_name = 1; +repeated Song songs = 2; ``` -If your field name contains a number, the number should appear after the letter -instead of after the underscore. For example, use `song_name1` instead of -`song_name_1` +## Oneof Names {#oneof-names} -## Repeated Fields {#repeated-fields} - -Use pluralized names for repeated fields. +Use lower_snake_case for oneof names. ```proto -repeated string keys = 1; - ... - repeated MyMessage accounts = 17; +oneof song_id { + string song_human_readable_id = 1; + int64 song_machine_id = 2; +} ``` ## Enums {#enums} -Use PascalCase (with an initial capital) for enum type names and -CAPITALS_WITH_UNDERSCORES for value names: +Use TitleCase for enum type names. + +Use UPPER_SNAKE_CASE for enum value names. ```proto enum FooBar { @@ -98,30 +137,54 @@ enum FooBar { } ``` -Each enum value should end with a semicolon, not a comma. +The first listed value should be a zero value enum and have the suffix of either +`_UNSPECIFIED` or `_UNKNOWN`. This value may be used as an unknown/default value +and should be distinct from any of the semantic values you expect to be +explicitly set. For more information on the unspecified enum value, see +[the Proto Best Practices page](/best-practices/dos-donts#unspecified-enum). -Since the enum values are semantically not scoped by their containing enum name, -the same value name in two sibling enums is not allowed. A name collision issue -is especially a risk for top level enums, since in that case their siblings may -be defined in another file which has the same package. To avoid these risks, it -is strongly recommended to either prefix every value with the enum name or to -nest the enum inside a containing message. +#### Enum Value Prefixing {#enum-value-prefixing} -Prefer using top-level enums with prefixed values over nesting them inside a -message. Since some languages don't support an enum being defined inside a -"struct" type, this ensures a consistent approach across binding languages. +Enum values are semantically considered to not be scoped by their containing +enum name, so the same name in two sibling enums is not allowed. For example, +the following would be rejected by protoc since the `SET` value defined in the +two enums are considered to be in the same scope: -The zero value enum should have the suffix `UNSPECIFIED`, because a server or -application that gets an unexpected enum value will mark the field as unset in -the proto instance. The field accessor will then return the default value, which -for enum fields is the first enum value. For more information on the unspecified -enum value, see -[the Proto Best Practices page](/best-practices/dos-donts#unspecified-enum). +```proto +enum CollectionType { + COLLECTION_TYPE_UNSPECIFIED = 0; + SET = 1; + MAP = 2; + ARRAY = 3; +} + +enum TennisVictoryType { + TENNIS_VICTORY_TYPE_UNSPECIFIED = 0; + GAME = 1; + SET = 2; + MATCH = 3; +} +``` + +Name collisions are a high risk when enums are defined at the top level of a +file (not nested inside a message definition); in that case the siblings include +enums defined in other files that set the same package, where protoc may not be +able to detect the collision has occurred at code generation time. + +To avoid these risks, it is strongly recommended to do one of: + +* Prefix every value with the enum name (converted to UPPER_SNAKE_CASE) +* Nest the enum inside a containing message + +Either option is enough to mitigate collision risks, but prefer top-level enums +with prefixed values over creating a message simply to mitigate the issue. Since +some languages don't support an enum being defined inside a "struct" type, +preferring prefixed values ensures a consistent approach across binding +languages. ## Services {#services} -If your `.proto` defines an RPC service, you should use PascalCase (with an -initial capital) for both the service name and any RPC method names: +Use TitleCase for service names and method names. ```proto service FooService { @@ -140,5 +203,31 @@ in Proto Best Practices. ## Things to Avoid {#avoid} -* Required fields (only for proto2) -* Groups (only for proto2) +### Required Fields {#required} + +Required fields are a way to enforce that a given field must be set when parsing +wire bytes, and otherwise refuse to parse the message. The required invariant is +generally not enforced on messages constructed in memory. Required fields were +removed in proto3. + +While enforcement of required fields at the schema level is intuitively +desirable, one of the primary design goals of protobuf is to support long term +schema evolution. No matter how obviously required a given field seems to be +today, there is a plausible future where the field should no longer be set (e.g. +an `int64 user_id` may need to migrate to a `UserId user_id` in the future). + +Especially in the case of middleware servers that may forward messages that they +don't really need to process, the semantics of `required` has proven too harmful +for those long-term evolution goals, and so is now very strongly discouraged. + +See +[Required is Strongly Deprecated](/programming-guides/proto2#required-deprecated). + +### Groups {#groups} + +Groups is an alternate syntax and wire format for nested messages. Groups are +considered deprecated in proto2 and were removed from proto3. You should use a +nested message definition and field of that type instead of using the group +syntax. + +See [groups](/programming-guides/proto2#groups). diff --git a/content/reference/cpp/api-docs/google.protobuf.util.message_differencer.md b/content/reference/cpp/api-docs/google.protobuf.util.message_differencer.md index 7ce93b523..baaa1a7d1 100644 --- a/content/reference/cpp/api-docs/google.protobuf.util.message_differencer.md +++ b/content/reference/cpp/api-docs/google.protobuf.util.message_differencer.md @@ -76,19 +76,19 @@ type = "docs"
#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
Abstract base class from which all IgnoreCriteria derive.
By adding IgnoreCriteria more complex ignore logic can be implemented. IgnoreCriteria are registered with AddIgnoreCriteria. For each compared field IsIgnored is called on each added IgnoreCriteria until one returns true or all return false. IsIgnored is called for fields where at least one side has a value.
Members | |
|---|---|
| IgnoreCriteria() |
virtual | ~IgnoreCriteria() |
virtual bool | IsIgnored(const Message & , const Message & , const FieldDescriptor * , const std::vector< SpecificField > & ) = 0Returns true if the field should be ignored. |
virtual bool | IsUnknownFieldIgnored(const Message & , const Message & , const SpecificField & , const std::vector< SpecificField > & )Returns true if the unknown field should be ignored. more... |
virtual bool IgnoreCriteria::IsUnknownFieldIgnored(
const Message & ,
const Message & ,
const SpecificField & ,
const std::vector< SpecificField > & )Returns true if the unknown field should be ignored.
Note: This will be called for unknown fields as well in which case
field.field will be null.-
#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
MapKeyComparator is used to determine if two elements have the same key when comparing elements of a repeated field as a map.
Members | |
|---|---|
| MapKeyComparator() |
virtual | ~MapKeyComparator() |
virtual bool | IsMatch(const Message & , const Message & , const std::vector< SpecificField > & ) const |
#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
Abstract base class from which all MessageDifferencer reporters derive.
The five Report* methods below will be called when a field has been added, deleted, modified, moved, or matched. The third argument is a vector of FieldDescriptor pointers which describes the chain of fields that was taken to find the current field. For example, for a field found in an embedded message, the vector will contain two FieldDescriptors. The first will be the field of the embedded message itself and the second will be the actual field in the embedded message that was added/deleted/modified. Fields will be reported in PostTraversalOrder. For example, given following proto, if both baz and quux are changed. foo {
-bar {
- baz: 1
- quux: 2
+class MessageDifferencer::MapKeyComparator
#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
MapKeyComparator is used to determine if two elements have the same key when comparing elements of a repeated field as a map.
Members | |
|---|---|
| MapKeyComparator() |
virtual | ~MapKeyComparator() |
virtual bool | IsMatch(const Message & , const Message & , const std::vector< SpecificField > & ) const |
#include <google/protobuf/util/message_differencer.h>
namespace google::protobuf::util
Abstract base class from which all MessageDifferencer reporters derive.
The five Report* methods below will be called when a field has been added, deleted, modified, moved, or matched. The third argument is a vector of FieldDescriptor pointers which describes the chain of fields that was taken to find the current field. For example, for a field found in an embedded message, the vector will contain two FieldDescriptors. The first will be the field of the embedded message itself and the second will be the actual field in the embedded message that was added/deleted/modified. Fields will be reported in PostTraversalOrder. For example, given the following proto, if both baz and mooo are changed. +
foo {
+ bar {
+ baz: 1
+ mooo: 2
+ }
}
-} ReportModified will be invoked with following order:
-ReportModified will be invoked with following order:
Known subclasses:
Members | |
|---|---|
| Reporter() |
virtual | ~Reporter() |
virtual void | ReportAdded(const Message & message1, const Message & message2, const std::vector< SpecificField > & field_path) = 0Reports that a field has been added into Message2. |
virtual void | ReportDeleted(const Message & message1, const Message & message2, const std::vector< SpecificField > & field_path) = 0Reports that a field has been deleted from Message1. |
virtual void | ReportModified(const Message & message1, const Message & message2, const std::vector< SpecificField > & field_path) = 0Reports that the value of a field has been modified. |
virtual void | ReportMoved(const Message & , const Message & , const std::vector< SpecificField > & )Reports that a repeated field has been moved to another location. more... |
virtual void | ReportMatched(const Message & , const Message & , const std::vector< SpecificField > & )Reports that two fields match. more... |
virtual void | ReportIgnored(const Message & , const Message & , const std::vector< SpecificField > & )Reports that two fields would have been compared, but the comparison has been skipped because the field was marked as 'ignored' using IgnoreField(). more... |
virtual void | ReportUnknownFieldIgnored(const Message & , const Message & , const std::vector< SpecificField > & )Report that an unknown field is ignored. more... |
virtual void Reporter::ReportMoved(
const Message & ,
const Message & ,
const std::vector< SpecificField > & )Reports that a repeated field has been moved to another location.
This only applies when using TreatAsSet or TreatAsMap() – see below. Also note that for any given field, ReportModified and ReportMoved are mutually exclusive. If a field has been both moved and modified, then only ReportModified will be called.
virtual void Reporter::ReportMatched(
const Message & ,
const Message & ,
const std::vector< SpecificField > & )Reports that two fields match.
Useful for doing side-by-side diffs. This function is mutually exclusive with ReportModified and ReportMoved. Note that you must call set_report_matches(true) before calling Compare to make use of this function.
diff --git a/content/reference/python/python-generated.md b/content/reference/python/python-generated.md index def91562b..9574c098e 100644 --- a/content/reference/python/python-generated.md +++ b/content/reference/python/python-generated.md @@ -405,6 +405,11 @@ assert foo.HasField("bar") ### Repeated Fields {#repeated-fields} +There are three types of repeated fields: scalar, enum, and message. Map fields +and oneof fields cannot be repeated. + +### Repeated Scalar and Enum Fields {#repeated-scalar} + Repeated fields are represented as an object that acts like a Python sequence. As with embedded messages, you cannot assign the field directly, but you can manipulate it. For example, given this message definition: