機能エディションの設定
このトピックでは、Edition 2023 に含まれる機能の概要を説明します。以降のエディションの機能はすべてこのトピックに追加されます。新しいエディションについては、ニュースセクションでお知らせします。
新しいスキーマ定義コンテンツで機能設定を構成する前に、それらを使用する理由を理解していることを確認してください。機能の思考停止は避けてください。
Prototiller
Prototiller は、proto2 および proto3 定義ファイルを Editions 構文に変換するコマンドラインツールです。まだリリースされていませんが、このトピック全体で参照されています。
機能
以下のセクションでは、Edition 2023 の機能を使用して設定可能なすべての動作について説明します。proto2 または proto3 の動作の維持では、proto 定義ファイルが proto2 または proto3 ファイルのように動作するように、デフォルトの動作をオーバーライドする方法を示します。エディションと機能が連携して動作を設定する方法の詳細については、Protobuf エディションの概要を参照してください。
以下の各セクションには、機能が適用されるスコープのエントリがあります。これには、ファイル、enum、メッセージ、またはフィールドが含まれます。次のサンプルは、各スコープに適用されるモック機能を示しています。
edition = "2023";
// File-scope definition
option features.bar = BAZ;
enum Foo {
// Enum-scope definition
option features.bar = QUX;
A = 1;
B = 2;
}
message Corge {
// Message-scope definition
option features.bar = QUUX;
// Field-scope definition
Foo A = 1 [features.bar = GRAULT];
}
この例では、フィールドスコープ機能定義の GRAULT
設定は、メッセージスコープの QUUX 設定をオーバーライドします。
features.enum_type
この機能は、定義されたセットに含まれていない enum 値の処理方法の動作を設定します。オープン enum とクローズド enum の詳細については、Enum の振る舞いを参照してください。
この機能は proto3 ファイルには影響を与えないため、このセクションには proto3 ファイルの変更前と変更後の例はありません。
利用可能な値
CLOSED:
クローズド enum は、範囲外の enum 値を不明なフィールドセットに格納します。OPEN:
オープン enum は、範囲外の値をフィールドに直接解析します。
適用可能なスコープ: ファイル、Enum
Edition 2023 のデフォルトの動作: OPEN
proto2 での動作: CLOSED
proto3 での動作: OPEN
次のコードサンプルは、proto2 ファイルを示しています。
syntax = "proto2";
enum Foo {
A = 2;
B = 4;
C = 6;
}
Prototiller を実行すると、同等のコードは次のようになる可能性があります。
edition = "2023";
enum Foo {
option features.enum_type = CLOSED;
A = 2;
B = 4;
C = 6;
}
features.field_presence
この機能は、フィールドの存在、つまり protobuf フィールドに値があるかどうかの概念を追跡する動作を設定します。
利用可能な値
LEGACY_REQUIRED
: フィールドは、解析およびシリアライゼーションに必須です。明示的に設定された値はすべて、(デフォルト値と同じであっても) ワイヤにシリアライズされます。EXPLICIT
: フィールドには明示的な存在追跡があります。明示的に設定された値はすべて、(デフォルト値と同じであっても) ワイヤにシリアライズされます。単数プリミティブフィールドの場合、has_*
関数はEXPLICIT
に設定されたフィールドに対して生成されます。IMPLICIT
: フィールドには存在追跡がありません。デフォルト値は、(明示的に設定されていても) ワイヤにシリアライズされません。has_*
関数は、IMPLICIT
に設定されたフィールドに対して生成されません。
適用可能なスコープ: ファイル、フィールド
Edition 2023 のデフォルト値: EXPLICIT
proto2 での動作: EXPLICIT
proto3 での動作: フィールドに optional
ラベルがある場合を除き IMPLICIT
であり、その場合は EXPLICIT
のように動作します。詳細については、Proto3 API での存在を参照してください。
次のコードサンプルは、proto2 ファイルを示しています。
syntax = "proto2";
message Foo {
required int32 x = 1;
optional int32 y = 2;
repeated int32 z = 3;
}
Prototiller を実行すると、同等のコードは次のようになる可能性があります。
edition = "2023";
message Foo {
int32 x = 1 [features.field_presence = LEGACY_REQUIRED];
int32 y = 2;
repeated int32 z = 3;
}
次は proto3 ファイルを示しています。
syntax = "proto3";
message Bar {
int32 x = 1;
optional int32 y = 2;
repeated int32 z = 3;
}
Prototiller を実行すると、同等のコードは次のようになる可能性があります。
edition = "2023";
option features.field_presence = IMPLICIT;
message Bar {
int32 x = 1;
int32 y = 2 [features.field_presence = EXPLICIT];
repeated int32 z = 3;
}
required
および optional
ラベルは Editions には存在しなくなりました。対応する動作は field_presence
機能で明示的に設定されるためです。
features.json_format
この機能は、JSON の解析とシリアライゼーションの動作を設定します。
この機能は proto3 ファイルには影響を与えないため、このセクションには proto3 ファイルの変更前と変更後の例はありません。Editions の動作は proto3 の動作と一致します。
利用可能な値
ALLOW
: ランタイムは JSON の解析とシリアライゼーションを許可する必要があります。JSON への明確なマッピングがあることを確認するために、proto レベルでチェックが適用されます。LEGACY_BEST_EFFORT
: ランタイムは、JSON の解析とシリアライゼーションを最大限に実行します。特定の proto は、ランタイムで未指定の動作 (多対 1 または 1 対多のマッピングなど) を引き起こす可能性のあるものが許可されています。
適用可能なスコープ: ファイル、メッセージ、Enum
Edition 2023 のデフォルトの動作: ALLOW
proto2 での動作: LEGACY_BEST_EFFORT
proto3 での動作: ALLOW
次のコードサンプルは、proto2 ファイルを示しています。
syntax = "proto2";
message Foo {
// Warning only
string bar = 1;
string bar_ = 2;
}
Prototiller を実行すると、同等のコードは次のようになる可能性があります。
edition = "2023";
features.json_format = LEGACY_BEST_EFFORT;
message Foo {
string bar = 1;
string bar_ = 2;
}
features.message_encoding
この機能は、シリアライズ時のフィールドのエンコーディングの動作を設定します。
この機能は proto3 ファイルには影響を与えないため、このセクションには proto3 ファイルの変更前と変更後の例はありません。
言語によっては、「グループのような」フィールドは、proto2 との下位互換性を提供するために、生成されたコードおよびテキスト形式で予期しない大文字小文字の区別がある場合があります。メッセージフィールドは、次のすべての条件が満たされている場合に「グループのような」フィールドになります。
DELIMITED
メッセージエンコーディングが指定されている- メッセージタイプは、フィールドと同じスコープで定義されている
- フィールド名は、小文字のタイプ名と完全に一致する
利用可能な値
LENGTH_PREFIXED
: フィールドは、メッセージ構造で説明されている LEN ワイヤタイプを使用してエンコードされます。DELIMITED
: メッセージ型のフィールドは、グループとしてエンコードされます。
適用可能なスコープ: ファイル、フィールド
Edition 2023 のデフォルトの動作: LENGTH_PREFIXED
proto2 での動作: グループを除き LENGTH_PREFIXED
。グループはデフォルトで DELIMITED
proto3 での動作: LENGTH_PREFIXED
。Proto3 は DELIMITED
をサポートしていません。
次のコードサンプルは、proto2 ファイルを示しています。
syntax = "proto2";
message Foo {
group Bar = 1 {
optional int32 x = 1;
repeated int32 y = 2;
}
}
Prototiller を実行すると、同等のコードは次のようになる可能性があります。
edition = "2023";
message Foo {
message Bar {
int32 x = 1;
repeated int32 y = 2;
}
Bar bar = 1 [features.message_encoding = DELIMITED];
}
features.repeated_field_encoding
この機能は、proto2/proto3 の packed
オプションが Editions に移行されたものです。
利用可能な値
PACKED
: プリミティブ型のrepeated
フィールドは、各要素を連結した単一の LEN レコードとしてエンコードされます。EXPANDED
:repeated
フィールドはそれぞれ、値ごとにフィールド番号でエンコードされます。
適用可能なスコープ: ファイル、フィールド
Edition 2023 のデフォルトの動作: PACKED
proto2 での動作: EXPANDED
proto3 での動作: PACKED
次のコードサンプルは、proto2 ファイルを示しています。
syntax = "proto2";
message Foo {
repeated int32 bar = 6 [packed=true];
repeated int32 baz = 7;
}
Prototiller を実行すると、同等のコードは次のようになる可能性があります。
edition = "2023";
option features.repeated_field_encoding = EXPANDED;
message Foo {
repeated int32 bar = 6 [features.repeated_field_encoding=PACKED];
repeated int32 baz = 7;
}
次は proto3 ファイルを示しています。
syntax = "proto3";
message Foo {
repeated int32 bar = 6;
repeated int32 baz = 7 [packed=false];
}
Prototiller を実行すると、同等のコードは次のようになる可能性があります。
edition = "2023";
message Foo {
repeated int32 bar = 6;
repeated int32 baz = 7 [features.repeated_field_encoding=EXPANDED];
}
features.utf8_validation
この機能は、文字列の検証方法を設定します。言語固有の utf8_validation
機能でオーバーライドされる場合を除き、すべての言語に適用されます。Java 言語固有の機能については、features.(pb.java).utf8_validation
を参照してください。
この機能は proto3 ファイルには影響を与えないため、このセクションには proto3 ファイルの変更前と変更後の例はありません。
利用可能な値
VERIFY
: ランタイムは UTF-8 を検証する必要があります。これはデフォルトの proto3 の動作です。NONE
: フィールドは、ワイヤ上の検証されていないbytes
フィールドのように動作します。パーサーは、無効な文字を置き換えるなど、このタイプのフィールドを予測不可能な方法で処理する場合があります。これはデフォルトの proto2 の動作です。
適用可能なスコープ: ファイル、フィールド
Edition 2023 のデフォルトの動作: VERIFY
proto2 での動作: NONE
proto3 での動作: VERIFY
次のコードサンプルは、proto2 ファイルを示しています。
syntax = "proto2";
message MyMessage {
string foo = 1;
}
Prototiller を実行すると、同等のコードは次のようになる可能性があります。
edition = "2023";
message MyMessage {
string foo = 1 [features.utf8_validation = NONE];
}
言語固有の機能
一部の機能は特定の言語に適用され、他の言語の同じ proto には適用されません。これらの機能を使用するには、言語のランタイムから対応する *_features.proto ファイルをインポートする必要があります。次のセクションの例では、これらのインポートを示しています。
features.(pb.cpp/pb.java).legacy_closed_enum
言語: C++、Java
この機能は、オープン enum 型のフィールドをクローズド enum のように動作させるかどうかを決定します。これにより、エディションは proto2 および proto3 からの Java および C++ での非準拠動作を再現できます。
この機能は proto3 ファイルには影響を与えないため、このセクションには proto3 ファイルの変更前と変更後の例はありません。
利用可能な値
true
:enum_type
に設定されている内容に関係なく、enum をクローズドとして扱います。false
:enum_type
で設定されている内容を尊重します。
適用可能なスコープ: ファイル、フィールド
Edition 2023 のデフォルトの動作: false
proto2 での動作: true
proto3 での動作: false
次のコードサンプルは、proto2 ファイルを示しています。
syntax = "proto2";
import "myproject/proto3file.proto";
message Msg {
myproject.proto3file.Proto3Enum name = 1;
}
Prototiller を実行すると、同等のコードは次のようになる可能性があります。
edition = "2023";
import "myproject/proto3file.proto";
import "google/protobuf/cpp_features.proto";
import "google/protobuf/java_features.proto";
message Msg {
myproject.proto3file.Proto3Enum name = 1 [
features.(pb.cpp).legacy_closed_enum = true,
features.(pb.java).legacy_closed_enum = true
];
}
features.(pb.cpp).string_type
言語: C++
この機能は、生成されたコードが文字列フィールドをどのように処理するかを決定します。これは proto2 および proto3 の ctype
オプションを置き換え、新しい string_view
機能を提供します。Edition 2023 では、ctype
または string_type
のいずれかをフィールドで指定できますが、両方を指定することはできません。
利用可能な値
VIEW
: フィールドのstring_view
アクセサーを生成します。これは将来のエディションでのデフォルトになります。CORD
: フィールドのCord
アクセサーを生成します。STRING
: フィールドのstring
アクセサーを生成します。
適用可能なスコープ: ファイル、フィールド
Edition 2023 のデフォルトの動作: STRING
proto2 での動作: STRING
proto3 での動作: STRING
次のコードサンプルは、proto2 ファイルを示しています。
syntax = "proto2";
message Foo {
optional string bar = 6;
optional string baz = 7 [ctype = CORD];
}
Prototiller を実行すると、同等のコードは次のようになる可能性があります。
edition = "2023";
import "google/protobuf/cpp_features.proto";
message Foo {
string bar = 6;
string baz = 7 [features.(pb.cpp).string_type = CORD];
}
次は proto3 ファイルを示しています。
syntax = "proto3"
message Foo {
string bar = 6;
string baz = 7 [ctype = CORD];
}
Prototiller を実行すると、同等のコードは次のようになる可能性があります。
edition = "2023";
import "google/protobuf/cpp_features.proto";
message Foo {
string bar = 6;
string baz = 7 [features.(pb.cpp).string_type = CORD];
}
features.(pb.java).utf8_validation
言語: Java
この言語固有の機能を使用すると、Java のみのフィールドレベルでファイルレベルの設定をオーバーライドできます。
この機能は proto3 ファイルには影響を与えないため、このセクションには proto3 ファイルの変更前と変更後の例はありません。
利用可能な値
DEFAULT
: 動作はfeatures.utf8_validation
で設定されたものと一致します。VERIFY
: ファイルレベルのfeatures.utf8_validation
設定をオーバーライドして、Java のみでVERIFY
を強制します。
適用可能なスコープ: フィールド、ファイル
Edition 2023 のデフォルトの動作: DEFAULT
proto2 での動作: DEFAULT
proto3 での動作: DEFAULT
次のコードサンプルは、proto2 ファイルを示しています。
syntax = "proto2";
option java_string_check_utf8=true;
message MyMessage {
string foo = 1;
string bar = 2;
}
Prototiller を実行すると、同等のコードは次のようになる可能性があります。
edition = "2023";
import "google/protobuf/java_features.proto";
option features.utf8_validation = NONE;
option features.(pb.java).utf8_validation = VERIFY;
message MyMessage {
string foo = 1;
}
features.(pb.java).large_enum
言語: Java
この言語固有の機能を使用すると、コンパイラーエラーを引き起こすことなく、Java で大規模な enum を処理する新しい機能を導入できます。
これは新しい動作であるため、proto2 または proto3 スキーマ定義ファイルには影響しません。
利用可能な値
true
: Java enum は新しい機能を使用します。false
: Java enum は引き続き Java enum を使用します。
適用可能なスコープ: Enum
Edition 2023 のデフォルトの動作: false
proto2 での動作: false
proto3 での動作: false
proto2 または proto3 の動作の維持
エディション形式に移行したいが、生成されたコードの動作方法の更新に対処したくない場合があります。このセクションでは、Prototiller ツールが .proto ファイルに加えて、Edition 2023 proto を proto2 または proto3 ファイルのように動作させる変更を示します。
これらの変更がファイルレベルで行われると、proto2 または proto3 のデフォルトが取得されます。下位レベル (メッセージレベル、フィールドレベル) でオーバーライドして、追加の動作の違い (required、proto3 optional など) を検討したり、定義をほぼ proto2 または proto3 のようにしたい場合に検討したりできます。
Prototiller を使用しない特定の理由がない限り、Prototiller を使用することをお勧めします。Prototiller を使用せずにこれらすべてを手動で適用するには、次のセクションの内容を .proto ファイルの先頭に追加します。
Proto2 の動作
edition = "2023";
import "google/protobuf/cpp_features.proto";
import "google/protobuf/java_features.proto";
option features.field_presence = EXPLICIT;
option features.enum_type = CLOSED;
option features.repeated_field_encoding = EXPANDED;
option features.json_format = LEGACY_BEST_EFFORT;
option features.utf8_validation = NONE;
option features.(pb.cpp).legacy_closed_enum = true;
option features.(pb.java).legacy_closed_enum = true;
Proto3 の動作
// proto3 behaviors
edition = "2023";
import "google/protobuf/cpp_features.proto";
import "google/protobuf/java_features.proto";
option features.field_presence = IMPLICIT;
option features.enum_type = OPEN;
// `packed=false` needs to be transformed to field-level repeated_field_encoding
// features in Editions syntax
option features.json_format = ALLOW;
option features.utf8_validation = VERIFY;
option features.(pb.cpp).legacy_closed_enum = false;
option features.(pb.java).legacy_closed_enum = false;
注意点と例外
このセクションでは、Prototiller を使用しない場合に手動で行う必要のある変更を示します。
前のセクションで示したファイルレベルのデフォルトを設定すると、ほとんどの場合デフォルトの動作が設定されますが、いくつかの例外があります。
optional
:optional
ラベルのすべてのインスタンスを削除し、ファイルレベルのデフォルトがIMPLICIT
の場合は、features.field_presence
をEXPLICIT
に変更します。required
:required
ラベルのすべてのインスタンスを削除し、フィールドレベルでfeatures.field_presence=LEGACY_REQUIRED
オプションを追加します。groups
:groups
を個別のメッセージにアンラップし、フィールドレベルでfeatures.message_encoding = DELIMITED
オプションを追加します。詳細については、features.message_encoding
を参照してください。java_string_check_utf8
: このファイルオプションを削除し、features.(pb.java).utf8_validation
に置き換えます。言語固有の機能で説明されているように、Java 機能をインポートする必要があります。packed
: エディション形式に変換された proto2 ファイルの場合、packed
フィールドオプションを削除し、Proto2 の動作で設定したEXPANDED
動作が必要ない場合は、フィールドレベルで[features.repeated_field_encoding=PACKED]
を追加します。エディション形式に変換された proto3 ファイルの場合、デフォルトの proto3 動作が必要ない場合は、フィールドレベルで[features.repeated_field_encoding=EXPANDED]
を追加します。