Skip to content

Commit 6f80780

Browse files
author
Luke Sneeringer
committed
Merge branch 'main' into aip-143
2 parents 0630658 + 17ef1fc commit 6f80780

24 files changed

Lines changed: 1577 additions & 2 deletions

.github/workflows/publish.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: publish
33
on:
44
push:
55
branches:
6-
- master
6+
- main
77
jobs:
88
github-pages:
99
runs-on: ubuntu-latest

.github/workflows/test.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@ name: test
33
on:
44
pull_request:
55
branches:
6-
- master
6+
- main
77
jobs:
88
build:
99
runs-on: ubuntu-latest

aip/general/0126/aip.md.j2

Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# Enumerations
2+
3+
It is common for a field to only accept or provide a discrete and limited set
4+
of values. In these cases, it can be useful to use enumerations (generally
5+
abbreviated "enums") in order to clearly communicate what the set of allowed
6+
values are.
7+
8+
## Guidance
9+
10+
APIs **may** expose enum objects for sets of values that are expected to change
11+
infrequently:
12+
13+
```typescript
14+
// Possible formats in which a book may be published.
15+
enum Format {
16+
// The printed format, in hardback.
17+
Hardback = 'HARDBACK',
18+
19+
// The printed format, in paperback.
20+
Paperback = 'PAPERBACK',
21+
22+
// An electronic book format.
23+
Ebook = 'EBOOK',
24+
25+
// An audio recording.
26+
Audiobook = 'AUDIOBOOK',
27+
}
28+
```
29+
30+
- All enum values **should** use a consistent case format across an
31+
organization. In many cases, this is dictated by the IDL the organization
32+
uses.
33+
- Enums **should** document whether the enum is frozen or they expect to add
34+
values in the future.
35+
36+
### When to use enums
37+
38+
Enums can be more accessible and readable than strings or booleans in many
39+
cases, but they do add overhead when they change. Therefore, enums **should**
40+
receive new values infrequently. While the definition of "infrequently" may
41+
change based on individual use cases, a good rule of thumb is no more than once
42+
a year. For enums that change frequently, the API **should** use a string and
43+
document the format.
44+
45+
**Note:** If an enumerated value needs to be shared across APIs, an enum
46+
**may** be used, but the assignment between enum values and their wire
47+
representation **must** match.
48+
49+
### Alternatives
50+
51+
Enums **should not** be used when there is a competing, widely-adopted standard
52+
representation (such as with [language codes][bcp-47] or [media types][]).
53+
Instead, that standard representation **should** be used. This is true even if
54+
only a small subset of values are permitted, because using enums in this
55+
situation often leads to frustrating lookup tables when trying to use multiple
56+
APIs together.
57+
58+
For enumerated values where the set of allowed values changes frequently, APIs
59+
**should** use a `string` field instead, and **must** document the allowed
60+
values. String fields with enumerated values **should** use a uniform case
61+
system (`snake_case`, `kebab-case`, etc.) throughout an organization.
62+
63+
Boolean fields **may** be used in situations where it is clear that no further
64+
flexibility will be needed. The default value **must** be `false`.
65+
66+
### Compatibility
67+
68+
Adding values to an enum has the potential to be disruptive to existing
69+
clients. Consider code written against the `Format` enum in an earlier version
70+
where only the first two options were available:
71+
72+
```typescript
73+
switch (book.format) {
74+
case Format.Hardback:
75+
// Do something...
76+
break;
77+
case Format.Paperback:
78+
// Do something...
79+
break;
80+
default:
81+
// When new enum values are introduced, pre-existing client code may
82+
// throw errors or act in unexpected ways.
83+
throw new Error('Unrecognized value.');
84+
}
85+
```
86+
87+
Services **may** add new values to existing enums; however, they **should** add
88+
enums carefully; think about what will happen if a client system does not know
89+
about a new value.
90+
91+
Additionally, in IDLs where enum values are presented in a specific order,
92+
services **should** only add new values to the end. An exception to this rule
93+
is if the enum conforms to an external standard (for example, an enum
94+
representing HTTP status codes would add a new 3xx value alongside the others,
95+
not at the end).
96+
97+
## Interface Definitions
98+
99+
{% tab proto %}
100+
101+
{% sample 'enum.proto', 'enum Format' %}
102+
103+
- The zero value of the enum **should** be the name of the enum itself followed
104+
by the suffix `_UNSPECIFIED`. The service **may** either allow or prohibit
105+
use of this value.
106+
- Enums which will only be used in a single message **should** be nested within
107+
that message. In this case, the enum **should** be declared immediately
108+
before it is used.
109+
- If multiple enums are in the same namespace, they **must not** share any
110+
values. (This is because enums do not provide their own namespace for their
111+
values in some languages.)
112+
- If an enumerated value needs to be shared across APIs, an enum **may** be
113+
used, but the assignment between the value names and the tag numbers **must**
114+
match.
115+
116+
**Note:** When using protocol buffers, it is impossible to distinguish between
117+
`false` and unset. If this is a requirement, an enum **may** be a better design
118+
choice (although `google.protobuf.BoolValue` is also available).
119+
120+
{% tab oas %}
121+
122+
{% sample 'enum.oas.yaml', 'format' %}
123+
124+
- Enumerated fields **should** be strings.
125+
- If the enum is optional, The `null` value **should** be used as the empty
126+
value, and **should** be the first value specified.
127+
128+
**Note:** If `null` is a valid value, OpenAPI 3.0 also requires that
129+
`nullable: true` is specified for the field.
130+
131+
{% endtabs %}
132+
133+
## Further reading
134+
135+
- For states, a special type of enum, see AIP-216.
136+
137+
[bcp-47]: https://en.wikipedia.org/wiki/IETF_language_tag
138+
[media types]: https://en.wikipedia.org/wiki/Media_type

aip/general/0126/aip.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
id: 126
3+
state: approved
4+
created: 2019-07-24
5+
placement:
6+
category: resource-design
7+
order: 60

aip/general/0126/enum.oas.yaml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
openapi: 3.0.3
3+
info:
4+
title: Library
5+
version: 1.0.0
6+
components:
7+
schema:
8+
Book:
9+
description: A representation of a single book.
10+
properties:
11+
name:
12+
type: string
13+
description: |
14+
The name of the book.
15+
Format: publishers/{publisher}/books/{book}
16+
isbn:
17+
type: string
18+
description: |
19+
The ISBN (International Standard Book Number) for this book.
20+
title:
21+
type: string
22+
description: The title of the book.
23+
authors:
24+
type: array
25+
items:
26+
type: string
27+
description: The author or authors of the book.
28+
rating:
29+
type: float
30+
description: The rating assigned to the book.
31+
format:
32+
type: string
33+
description: The format of the book.
34+
nullable: true
35+
enum:
36+
- null
37+
- HARDCOVER
38+
- PAPERBACK
39+
- EBOOK
40+
- AUDIOBOOK

aip/general/0126/enum.proto

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
// Copyright 2020 Google LLC
2+
//
3+
// Licensed under the Apache License, Version 2.0 (the "License");
4+
// you may not use this file except in compliance with the License.
5+
// You may obtain a copy of the License at
6+
//
7+
// https://www.apache.org/licenses/LICENSE-2.0
8+
//
9+
// Unless required by applicable law or agreed to in writing, software
10+
// distributed under the License is distributed on an "AS IS" BASIS,
11+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12+
// See the License for the specific language governing permissions and
13+
// limitations under the License.
14+
15+
syntax = "proto3";
16+
17+
import "google/api/resource.proto";
18+
19+
// A representation of a book.
20+
message Book {
21+
option (google.api.resource) = {
22+
type: "library.googleapis.com/Book"
23+
pattern: "publishers/{publisher}/books/{book}"
24+
};
25+
26+
// The name of the book.
27+
// Format: publishers/{publisher}/books/{book}
28+
string name = 1;
29+
30+
// The ISBN (International Standard Book Number) for this book.
31+
string isbn = 2;
32+
33+
// The title of the book.
34+
string title = 3;
35+
36+
// The author or authors of the book.
37+
repeated string authors = 4;
38+
39+
// The rating assigned to the book.
40+
float rating = 5;
41+
42+
// Possible formats in which the book may be published.
43+
enum Format {
44+
// Default value. This value is unused.
45+
FORMAT_UNSPECIFIED = 0;
46+
47+
// The printed format, in hardback.
48+
HARDBACK = 1;
49+
50+
// The printed format, in paperback.
51+
PAPERBACK = 2;
52+
53+
// An electronic book format.
54+
EBOOK = 3;
55+
56+
// An audio recording.
57+
AUDIOBOOK = 4;
58+
}
59+
60+
// The format of the book.
61+
Format format = 6;
62+
}

aip/general/0141/aip.md

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
# Quantities
2+
3+
Many services need to represent a discrete quantity of items (number of bytes,
4+
number of miles, number of nodes, etc.).
5+
6+
## Guidance
7+
8+
Quantities with a clear unit of measurement (such as bytes, miles, and so on)
9+
**must** include the unit of measurement as the suffix. When appropriate and
10+
unambiguous, units **should** use generally accepted abbreviations (for
11+
example, `distance_km` rather than `distance_kilometers`).
12+
13+
```typescript
14+
// A representation of a non-stop air route.
15+
interface Route {
16+
// The airport where the route begins.
17+
origin: string;
18+
19+
// The destination airport.
20+
destination: string;
21+
22+
// The distance between the origin and destination airports.
23+
// This value is also used to determine the credited frequent flyer miles.
24+
distance_miles: number;
25+
}
26+
```
27+
28+
If the quantity is a number of items (for example, the number of nodes in a
29+
cluster), then the field **should** use the suffix `_count` (**not** the prefix
30+
`num_`):
31+
32+
```typescript
33+
// A cluster of individual nodes.
34+
interface Cluster {
35+
// The number of nodes in the cluster.
36+
node_count: number;
37+
}
38+
```
39+
40+
**Note:** Fields **must not** use unsigned integer types, because many
41+
programming languages and systems do not support them well.
42+
43+
### Specialized messages
44+
45+
It is sometimes useful to create a message that represents a particular
46+
quantity. This is particularly valuable in two situations.
47+
48+
- Grouping two or more individual quantities together.
49+
- Representing a common concept where the unit of measurement may itself vary.
50+
51+
Consider the example of money, which could need to do both of these:
52+
53+
```typescript
54+
// A representation of an amount of money, in an arbitrary currency.
55+
interface Money {
56+
// The 3-letter currency code defined in ISO 4217.
57+
currency_code: string;
58+
59+
// The whole units of the amount.
60+
// For example if `currency_code` is "USD", then 1 unit is one US dollar.
61+
units: bigint;
62+
63+
// Number of nano (10^-9) units of the amount.
64+
// The value must be between -999,999,999 and +999,999,999 inclusive.
65+
// If `units` is positive, `nanos` must be positive or zero.
66+
// If `units` is zero, `nanos` can be positive, zero, or negative.
67+
// If `units` is negative, `nanos` must be negative or zero.
68+
// For example $-1.75 is represented as `units`=-1 and `nanos`=-750,000,000.
69+
nanos: number;
70+
}
71+
```
72+
73+
APIs **may** create structs to represent quantities when appropriate. When
74+
using these structs as fields, APIs **should** use the name of the struct as
75+
the suffix for the field name if it makes intuitive sense to do so.
76+
77+
## Changelog
78+
79+
- **2019-09-13**: Added the prohibition on unsigned types.

aip/general/0141/aip.yaml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
id: 141
3+
state: approved
4+
created: 2019-07-18
5+
placement:
6+
category: fields
7+
order: 20

0 commit comments

Comments
 (0)