Skip to content

Commit 3b602b2

Browse files
authored
Merge pull request #67 from Logofile/sync
Project import generated by Copybara.
2 parents 09b5397 + a3e4794 commit 3b602b2

File tree

6 files changed

+481
-21
lines changed

6 files changed

+481
-21
lines changed

content/editions/_index.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
+++
2+
title = "Protobuf Editions"
3+
weight = 41
4+
description = "Topics related to the Protobuf Editions functionality."
5+
type = "docs"
6+
+++
7+
8+
* [Protocol Buffers Overview](/editions/overview)

content/editions/overview.md

Lines changed: 284 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,284 @@
1+
+++
2+
title = "Protobuf Editions Overview"
3+
weight = 42
4+
description = "An overview of the Protobuf Editions functionality."
5+
type = "docs"
6+
+++
7+
8+
Protobuf Editions replace the proto2 and proto3 designations that we have used
9+
for Protocol Buffers. Instead of adding `syntax = "proto2"` or `syntax =
10+
"proto3"` at the top of proto definition files, you use an edition number, such
11+
as `edition = "2024"`, to specify the default behaviors your file will have.
12+
Editions enable the language to evolve incrementally over time.
13+
14+
Instead of the hardcoded behaviors that older versions have had, editions
15+
represent a collection of features with a default value (behavior) per feature.
16+
Features are options on a file, message, field, enum, and so on, that specify
17+
the behavior of protoc, the code generators, and protobuf runtimes. You can
18+
explicitly override a behavior at those different levels (file, message, field,
19+
...) when your needs don't match the default behavior for the edition you've
20+
selected. You can also override your overrides. The
21+
[section later in this topic on inheritance](#inheritance) goes into more detail
22+
on that.
23+
24+
## Lifecycles of a Feature {#lifecycles}
25+
26+
Editions provide the fundamental increments for the lifecycle of a feature.
27+
Features have an expected lifecycle: introducing
28+
it, changing its default behavior, deprecating it, and then removing it. For
29+
example:
30+
31+
1. Edition 2031 creates `feature.amazing_new_feature` with a default value of
32+
`false`. This value maintains the same behavior as all earlier editions.
33+
That is, it defaults to no impact.
34+
35+
2. Developers update their .proto files to `edition = "2031"`.
36+
37+
3. A later edition, such as edition 2033, switches the default of
38+
`feature.amazing_new_feature` from `false` to `true`. This is the desired
39+
behavior for all protos, and the reason that the protobuf team created the
40+
feature.
41+
42+
Using the Prototiller tool to migrate earlier versions of proto files to
43+
edition 2033 adds explicit `feature.amazing_new_feature = false` entries as
44+
needed to continue to retain the previous behavior. Developers remove these
45+
newly-added settings when they want the new behavior to apply to their
46+
.proto files.
47+
48+
<!-- mdformat off (preserve single lines/no wrapping) -->
49+
50+
5. At some point, `feature.amazing_new_feature` is marked deprecated in an edition and removed in a later one. {value=5}
51+
52+
When a feature is removed, the code generators for that behavior and the
53+
runtime libraries that support it may also be removed. The timelines will be
54+
generous, though. Following the example in the earlier steps of the
55+
lifecycle, the deprecation might happen in edition 2034 but not be removed
56+
until edition 2036, roughly two years later. Removing a feature will always
57+
initiate a major version bump.
58+
59+
<!-- mdformat on -->
60+
61+
Because of this lifecycle, any `.proto` file that does not use deprecated
62+
features has a no-op upgrade from one edition to the next.
63+
You will have the full
64+
window of the Google migration plus the deprecation window to upgrade your code.
65+
66+
The preceding lifecycle example used boolean values for the features, but
67+
features may also use enums. For example, `features.field_presence` has values
68+
`LEGACY_REQUIRED`, `EXPLICIT`, and `IMPLICIT.`
69+
70+
## Migrating to Protobuf Editions {#migrating}
71+
72+
Editions won't break existing binaries and don't change a message's binary,
73+
text, or JSON serialization format. The first edition is as minimally disruptive
74+
as possible. The first edition establishes the baseline and combines proto2 and
75+
proto3 definitions into a new single definition format.
76+
77+
When the subsequent editions are released, default behaviors for features may
78+
change. You can have Prototiller do a no-op transformation of your .proto file
79+
or you can choose to accept some or all of the new behaviors. Editions are
80+
planned to be released roughly once a year.
81+
82+
### Proto2 to Editions {#proto2-migration}
83+
84+
This section shows a proto2 file, and what it might look like after running the
85+
Prototiller tool to change the definition files to use Protobuf Editions syntax.
86+
87+
<section class="tabs">
88+
89+
#### Proto2 syntax {.new-tab}
90+
91+
```proto
92+
// proto2 file
93+
syntax = "proto2";
94+
95+
message Player {
96+
// in proto2, optional fields have explicit presence
97+
optional string name = 1;
98+
// proto2 still supports the problematic "required" field rule
99+
required int32 id = 2;
100+
// in proto2 this is not packed by default
101+
repeated int32 scores = 3;
102+
103+
enum Handed {
104+
HANDED_UNSPECIFIED = 0,
105+
HANDED_LEFT = 1,
106+
HANDED_RIGHT = 2,
107+
HANDED_AMBIDEXTROUS = 3,
108+
}
109+
110+
// in proto2 enums are closed
111+
optional Handed handed = 4;
112+
}
113+
```
114+
115+
#### Editions syntax {.new-tab}
116+
117+
```proto
118+
// Edition version of proto2 file
119+
edition = "2023";
120+
121+
message Player {
122+
// fields have explicit presence, so no explicit setting needed
123+
string name = 1;
124+
// to match the proto2 behavior, LEGACY_REQUIRED is set at the field level
125+
int32 id = 2 [features.field_presence = LEGACY_REQUIRED];
126+
// to match the proto2 behavior, EXPANDED is set at the field level
127+
repeated int32 scores = 3 [features.repeated_field_encoding = EXPANDED];
128+
129+
enum Handed {
130+
// this overrides the default edition 2023 behavior, which is OPEN
131+
option features.enum_type = CLOSED;
132+
HANDED_UNSPECIFIED = 0,
133+
HANDED_LEFT = 1,
134+
HANDED_RIGHT = 2,
135+
HANDED_AMBIDEXTROUS = 3,
136+
}
137+
138+
Handed handed = 4;
139+
}
140+
```
141+
142+
</section>
143+
144+
### Proto3 to Editions {#proto3-migration}
145+
146+
This section shows a proto3 file, and what it might look like after running the
147+
Prototiller tool to change the definition files to use Protobuf Editions syntax.
148+
149+
<section class="tabs">
150+
151+
#### Proto3 syntax {.new-tab}
152+
153+
```proto
154+
// proto3 file
155+
syntax = "proto3";
156+
157+
message Player {
158+
// in proto3, optional fields have explicit presence
159+
optional string name = 1;
160+
// in proto3 no specified field rule defaults to implicit presence
161+
int32 id = 2;
162+
// in proto3 this is packed by default
163+
repeated int32 scores = 3;
164+
165+
enum Handed {
166+
HANDED_UNSPECIFIED = 0,
167+
HANDED_LEFT = 1,
168+
HANDED_RIGHT = 2,
169+
HANDED_AMBIDEXTROUS = 3,
170+
}
171+
172+
// in proto3 enums are open
173+
optional Handed handed = 4;
174+
}
175+
```
176+
177+
#### Editions syntax {.new-tab}
178+
179+
```proto
180+
// Editions version of proto3 file
181+
edition = "2023";
182+
183+
message Player {
184+
// fields have explicit presence, so no explicit setting needed
185+
string name = 1;
186+
// to match the proto3 behavior, IMPLICIT is set at the field level
187+
int32 id = 2 [features.field_presence = IMPLICIT];
188+
// PACKED is the default state, and is provided just for illustration
189+
repeated int32 scores = 3 [features.repeated_field_encoding = PACKED];
190+
191+
enum Handed {
192+
HANDED_UNSPECIFIED = 0,
193+
HANDED_LEFT = 1,
194+
HANDED_RIGHT = 2,
195+
HANDED_AMBIDEXTROUS = 3,
196+
}
197+
198+
Handed handed = 4 [features.field_presence = IMPLICIT];
199+
}
200+
```
201+
202+
</section>
203+
204+
### Inheritance {#inheritance}
205+
206+
Editions syntax supports inheritance, with a per-feature list of allowed
207+
targets. For example, in the first edition, features can be specified at only
208+
the file level or the lowest level of granularity. Inheritance enables you to
209+
set the default behavior for a feature across an entire file, and then override
210+
that behavior at the message, field, enum, enum value, oneof, service, or
211+
method. Settings made at a higher level (file, message) apply when no setting is
212+
made within the same scope (field, enum value). Any features not explicitly set
213+
conform to the behavior defined in the edition version used for the .proto file.
214+
215+
The following code sample shows some features being set at the file, message,
216+
and enum level. The settings are in the highlighted lines:
217+
218+
```proto {highlight="lines:3,7,16"}
219+
edition = "2023";
220+
221+
option features.enum_type = CLOSED;
222+
223+
message Person {
224+
string name = 1;
225+
int32 id = 2 [features.presence = IMPLICIT];
226+
227+
enum Pay_Type
228+
PAY_TYPE_UNSPECIFIED = 1,
229+
PAY_TYPE_SALARY = 2,
230+
PAY_TYPE_HOURLY = 3
231+
}
232+
233+
enum Employment {
234+
option features.enum_type = OPEN;
235+
EMPLOYMENT_UNSPECIFIED = 0,
236+
EMPLOYMENT_FULLTIME = 1,
237+
EMPLOYMENT_PARTTIME = 2,
238+
}
239+
Employment employment = 4;
240+
}
241+
```
242+
243+
In the preceding example, the presence feature is set to `IMPLICIT`; it would
244+
default to `EXPLICIT` if it wasn't set. The `Pay_Type` `enum` will be `CLOSED`,
245+
as it inherits the file-level setting. The `Employment` `enum`, though, will be
246+
`OPEN`, as it is set within the enum.
247+
248+
### Prototiller {#prototiller}
249+
250+
We provide both a migration guide and migration tooling that ease the migration
251+
to editions. The tool, called Prototiller, will enable you to:
252+
253+
* convert proto2 and proto3 definition files to the new editions syntax, at
254+
scale
255+
* migrate files from one edition to another
256+
* manipulate proto files in other ways
257+
258+
### Backward Compatibility {#compatibility}
259+
260+
We are building Protobuf Editions to be as minimally disruptive as possible. For
261+
example, you can import proto2 and proto3 definitions into editions-based
262+
definition files, and vice versa:
263+
264+
```proto
265+
// file myproject/foo.proto
266+
syntax = "proto2";
267+
268+
enum Employment {
269+
EMPLOYMENT_UNSPECIFIED = 0,
270+
EMPLOYMENT_FULLTIME = 1,
271+
EMPLOYMENT_PARTTIME = 2,
272+
}
273+
```
274+
275+
```proto
276+
// file myproject/edition.proto
277+
edition = "2023";
278+
279+
import "myproject/foo.proto";
280+
```
281+
282+
While the generated code changes when you move from proto2 or proto3 to
283+
editions, the wire format does not. You'll still be able to access proto2 and
284+
proto3 data files or file streams using your editions-syntax proto definitions.

0 commit comments

Comments
 (0)