テキスト形式言語仕様
この形式は、例えば .proto スキーマ内のテキスト形式とは異なります。このドキュメントでは、ISO/IEC 14977 EBNF で指定された構文を使用した参照ドキュメントが含まれています。
注意
これは、C++ テキスト形式の実装からリバースエンジニアリングされたドラフト仕様であり、今後の議論やレビューに基づいて変更される可能性があります。サポートされている言語間でテキスト形式の一貫性を保つ努力がなされていますが、非互換性が存在する可能性があります。例
convolution_benchmark {
label: "NHWC_128x20x20x56x160"
input {
dimension: [128, 56, 20, 20]
data_type: DATA_HALF
format: TENSOR_NHWC
}
}
解析の概要
この仕様の言語要素は、字句カテゴリと構文カテゴリに分けられます。字句要素は、記述どおりに入力テキストと正確に一致する必要がありますが、構文要素はオプションの WHITESPACE および COMMENT トークンで区切られる場合があります。
例えば、符号付き浮動小数点値は、符号 (-) と FLOAT リテラルの2つの構文要素で構成されます。符号と数値の間にはオプションの空白とコメントが存在する場合がありますが、数値内には存在しません。例
value: -2.0 # Valid: no additional whitespace.
value: - 2.0 # Valid: whitespace between '-' and '2.0'.
value: -
# comment
2.0 # Valid: whitespace and comments between '-' and '2.0'.
value: 2 . 0 # Invalid: the floating point period is part of the lexical
# element, so no additional whitespace is allowed.
特別な注意が必要なエッジケースが1つあります。数値トークン (FLOAT, DEC_INT, OCT_INT, または HEX_INT) の直後に IDENT トークンが続くことはできません。例
foo: 10 bar: 20 # Valid: whitespace separates '10' and 'bar'
foo: 10,bar: 20 # Valid: ',' separates '10' and 'bar'
foo: 10[com.foo.ext]: 20 # Valid: '10' is followed immediately by '[', which is
# not an identifier.
foo: 10bar: 20 # Invalid: no space between '10' and identifier 'bar'.
字句要素
以下に記述される字句要素は、2つのカテゴリに分類されます。大文字の主要要素と小文字のフラグメントです。主要要素のみが、構文解析中に使用されるトークンの出力ストリームに含まれます。フラグメントは、主要要素の構築を簡素化するためにのみ存在します。
入力テキストを解析するときは、最も長く一致する主要要素が優先されます。例
value: 10 # '10' is parsed as a DEC_INT token.
value: 10f # '10f' is parsed as a FLOAT token, despite containing '10' which
# would also match DEC_INT. In this case, FLOAT matches a longer
# subsequence of the input.
文字
char = ? Any non-NUL unicode character ? ;
newline = ? ASCII #10 (line feed) ? ;
letter = "A" | "B" | "C" | "D" | "E" | "F" | "G" | "H" | "I" | "J" | "K" | "L" | "M"
| "N" | "O" | "P" | "Q" | "R" | "S" | "T" | "U" | "V" | "W" | "X" | "Y" | "Z"
| "a" | "b" | "c" | "d" | "e" | "f" | "g" | "h" | "i" | "j" | "k" | "l" | "m"
| "n" | "o" | "p" | "q" | "r" | "s" | "t" | "u" | "v" | "w" | "x" | "y" | "z"
| "_" ;
oct = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" ;
dec = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9" ;
hex = "0" | "1" | "2" | "3" | "4" | "5" | "6" | "7" | "8" | "9"
| "A" | "B" | "C" | "D" | "E" | "F"
| "a" | "b" | "c" | "d" | "e" | "f" ;
空白とコメント
COMMENT = "#", { char - newline }, [ newline ] ;
WHITESPACE = " "
| newline
| ? ASCII #9 (horizontal tab) ?
| ? ASCII #11 (vertical tab) ?
| ? ASCII #12 (form feed) ?
| ? ASCII #13 (carriage return) ? ;
識別子
IDENT = letter, { letter | dec } ;
数値リテラル
dec_lit = "0"
| ( dec - "0" ), { dec } ;
float_lit = ".", dec, { dec }, [ exp ]
| dec_lit, ".", { dec }, [ exp ]
| dec_lit, exp ;
exp = ( "E" | "e" ), [ "+" | "-" ], dec, { dec } ;
DEC_INT = dec_lit
OCT_INT = "0", oct, { oct } ;
HEX_INT = "0", ( "X" | "x" ), hex, { hex } ;
FLOAT = float_lit, [ "F" | "f" ]
| dec_lit, ( "F" | "f" ) ;
10進整数は、F および f サフィックスを使用することで浮動小数点値としてキャストできます。例
foo: 10 # This is an integer value.
foo: 10f # This is a floating-point value.
foo: 1.0f # Also optional for floating-point literals.
文字列リテラル
STRING = single_string | double_string ;
single_string = "'", { escape | char - "'" - newline - "\" }, "'" ;
double_string = '"', { escape | char - '"' - newline - "\" }, '"' ;
escape = "\a" (* ASCII #7 (bell) *)
| "\b" (* ASCII #8 (backspace) *)
| "\f" (* ASCII #12 (form feed) *)
| "\n" (* ASCII #10 (line feed) *)
| "\r" (* ASCII #13 (carriage return) *)
| "\t" (* ASCII #9 (horizontal tab) *)
| "\v" (* ASCII #11 (vertical tab) *)
| "\?" (* ASCII #63 (question mark) *)
| "\\" (* ASCII #92 (backslash) *)
| "\'" (* ASCII #39 (apostrophe) *)
| '\"' (* ASCII #34 (quote) *)
| "\", oct, [ oct, [ oct ] ] (* octal escaped byte value *)
| "\x", hex, [ hex ] (* hexadecimal escaped byte value *)
| "\u", hex, hex, hex, hex (* Unicode code point up to 0xffff *)
| "\U000",
hex, hex, hex, hex, hex (* Unicode code point up to 0xfffff *)
| "\U0010",
hex, hex, hex, hex ; (* Unicode code point between 0x100000 and 0x10ffff *)
8進エスケープシーケンスは、最大3桁の8進数字を消費します。追加の数字はエスケープされずに渡されます。たとえば、入力 \1234 をアンエスケープする場合、パーサーは3桁の8進数字 (123) を消費してバイト値 0x53 (ASCII 'S'、10進数で83) をアンエスケープし、続く '4' はバイト値 0x34 (ASCII '4') として渡されます。正しい解析を確実にするには、必要に応じて先行ゼロを使用して、\000、\001、\063、\377 のように3桁の8進数字で8進エスケープシーケンスを表現します。\5Hello のように、数字の後に非数字文字が続く場合、3桁未満の数字が消費されます。
16進エスケープシーケンスは、最大2桁の16進数字を消費します。たとえば、\x213 をアンエスケープする場合、パーサーは最初の2桁 (21) のみを消費してバイト値 0x21 (ASCII '!') をアンエスケープします。正しい解析を確実にするには、必要に応じて先行ゼロを使用して、\x00、\x01、\xFF のように2桁の16進数字で16進エスケープシーケンスを表現します。\xFHello や \x3world のように、数字の後に非16進文字が続く場合、2桁未満の数字が消費されます。
バイトごとのエスケープは、型が bytes のフィールドにのみ使用してください。型が string のフィールドでバイトごとのエスケープを使用することも可能ですが、これらのエスケープシーケンスは有効な UTF-8 シーケンスを形成する必要があります。バイトごとのエスケープを使用して UTF-8 シーケンスを表現すると、エラーが発生しやすくなります。string 型フィールドのリテラル内の印字不可能な文字や改行文字には、Unicode エスケープシーケンスを使用することをお勧めします。
長い文字列は、連続する行で複数の引用符付き文字列に分割できます。例えば
quote:
"When we got into office, the thing that surprised me most was to find "
"that things were just as bad as we'd been saying they were.\n\n"
" -- John F. Kennedy"
Unicode コードポイントは、Unicode 13 表 A-1 拡張 BNF に従って解釈され、UTF-8 でエンコードされます。
警告
C++ の実装では現在、エスケープされた上位サロゲートコードポイントを UTF-16 コードユニットとして解釈し、別々の引用符付き文字列に分割することなく、直後に\uHHHH の下位サロゲートコードポイントが続くことを想定しています。さらに、ペアになっていないサロゲートは、やはり無効な UTF-8 として直接レンダリングされます。これらはどちらも非準拠の動作であり[^surrogates]、依存すべきではありません。構文要素
メッセージ
メッセージはフィールドの集合です。テキスト形式ファイルは単一のメッセージです。
Message = { Field } ;
リテラル
フィールドリテラル値は、数値、文字列、または true や enum 値などの識別子になります。
String = STRING, { STRING } ;
Float = [ "-" ], FLOAT ;
Identifier = IDENT ;
SignedIdentifier = "-", IDENT ; (* For example, "-inf" *)
DecSignedInteger = "-", DEC_INT ;
OctSignedInteger = "-", OCT_INT ;
HexSignedInteger = "-", HEX_INT ;
DecUnsignedInteger = DEC_INT ;
OctUnsignedInteger = OCT_INT ;
HexUnsignedInteger = HEX_INT ;
単一の文字列値は、オプションの空白で区切られた複数の引用符付き部分で構成できます。例
a_string: "first part" 'second part'
"third part"
no_whitespace: "first""second"'third''fourth'
フィールド名
含まれるメッセージの一部であるフィールドは、名前として単純な Identifiers を使用します。Extension および Any フィールド名は角括弧で囲まれ、完全修飾されます。Any フィールド名は、type.googleapis.com/ のような修飾ドメイン名がプレフィックスとして付けられます。
FieldName = ExtensionName | AnyName | IDENT ;
ExtensionName = "[", TypeName, "]" ;
AnyName = "[", Domain, "/", TypeName, "]" ;
TypeName = IDENT, { ".", IDENT } ;
Domain = IDENT, { ".", IDENT } ;
通常のフィールドと拡張フィールドには、スカラー値またはメッセージ値を含めることができます。Any フィールドは常にメッセージです。例
reg_scalar: 10
reg_message { foo: "bar" }
[com.foo.ext.scalar]: 10
[com.foo.ext.message] { foo: "bar" }
any_value {
[type.googleapis.com/com.foo.any] { foo: "bar" }
}
未知のフィールド
テキスト形式パーサーは、フィールド名の代わりに生のフィールド番号で表現された不明なフィールドをサポートできません。なぜなら、6つのワイヤータイプのうち3つがテキスト形式で同じように表現されるからです。一部のテキスト形式シリアライザーの実装では、フィールド番号と値の数値表現を使用する形式で不明なフィールドをエンコードしますが、ワイヤータイプ情報が無視されるため、これは本質的に損失を伴います。比較として、ワイヤー形式は、各フィールドタグにワイヤータイプを (field_number << 3) | wire_type として含めるため、損失を伴いません。エンコーディングの詳細については、エンコーディングのトピックを参照してください。
メッセージスキーマからのフィールドタイプに関する情報がないと、値はワイヤー形式のプロトメッセージに正しくエンコードできません。
フィールド
フィールド値は、リテラル (文字列、数値、または識別子) またはネストされたメッセージにすることができます。
Field = ScalarField | MessageField ;
MessageField = FieldName, [ ":" ], ( MessageValue | MessageList ) [ ";" | "," ];
ScalarField = FieldName, ":", ( ScalarValue | ScalarList ) [ ";" | "," ];
MessageList = "[", [ MessageValue, { ",", MessageValue } ], "]" ;
ScalarList = "[", [ ScalarValue, { ",", ScalarValue } ], "]" ;
MessageValue = "{", Message, "}" | "<", Message, ">" ;
ScalarValue = String
| Float
| Identifier
| SignedIdentifier
| DecSignedInteger
| OctSignedInteger
| HexSignedInteger
| DecUnsignedInteger
| OctUnsignedInteger
| HexUnsignedInteger ;
フィールド名と値の間のデリミタ : はスカラーフィールドでは必須ですが、メッセージフィールド (リストを含む) ではオプションです。例
scalar: 10 # Valid
scalar 10 # Invalid
scalars: [1, 2, 3] # Valid
scalars [1, 2, 3] # Invalid
message: {} # Valid
message {} # Valid
messages: [{}, {}] # Valid
messages [{}, {}] # Valid
メッセージフィールドの値は、中括弧または山括弧で囲むことができます。
message: { foo: "bar" }
message: < foo: "bar" >
repeated とマークされたフィールドは、フィールドを繰り返す、特別な [] リスト構文を使用する、またはその両方の組み合わせによって複数の値を指定できます。値の順序は維持されます。例
repeated_field: 1
repeated_field: 2
repeated_field: [3, 4, 5]
repeated_field: 6
repeated_field: [7, 8, 9]
は以下と同等です。
repeated_field: [1, 2, 3, 4, 5, 6, 7, 8, 9]
非 repeated フィールドはリスト構文を使用できません。たとえば、[0] は optional または required フィールドでは無効です。optional とマークされたフィールドは省略するか、1回だけ指定できます。required とマークされたフィールドは、厳密に1回指定する必要があります。required は proto2 のレガシー機能であり、proto3 では利用できません。エディションで features.field_presence = LEGACY_REQUIRED を使用しているメッセージには、下位互換性があります。
関連付けられた .proto メッセージに指定されていないフィールドは、フィールド名がメッセージの reserved フィールドリストに存在する場合を除き、許可されません。reserved フィールドは、どのような形式 (スカラー、リスト、メッセージ) で存在していても、テキスト形式では単純に無視されます。
値の型
フィールドに関連付けられた .proto 値の型が分かっている場合、以下の値の説明と制約が適用されます。このセクションの目的のため、以下のコンテナ要素を宣言します。
signedInteger = DecSignedInteger | OctSignedInteger | HexSignedInteger ;
unsignedInteger = DecUnsignedInteger | OctUnsignedInteger | HexUnsignedInteger ;
integer = signedInteger | unsignedInteger ;
| .proto 型 | 値 |
|---|---|
float, double | Float、DecSignedInteger、または DecUnsignedInteger 要素、あるいは IDENT 部分が _"inf"、"infinity"、または"nan"* (大文字小文字を区別しない) に等しい Identifier または SignedIdentifier 要素。オーバーフローは無限大または負の無限大として扱われます。8進数および16進数の値は無効です。注記: _"nan"_ は Quiet NaN として解釈されるべきです |
int32, sint32, sfixed32 | 範囲 -0x80000000 から 0x7FFFFFFF の任意の integer 要素。 |
int64, sint64, sfixed64 | 範囲 -0x8000000000000000 から 0x7FFFFFFFFFFFFFFF の任意の integer 要素。 |
uint32, fixed32 | 範囲 0 から 0xFFFFFFFF の任意の unsignedInteger 要素。符号付きの値 (-0) は無効であることに注意してください。 |
uint64, fixed64 | 範囲 0 から 0xFFFFFFFFFFFFFFFF の任意の unsignedInteger 要素。符号付きの値 (-0) は無効であることに注意してください。 |
string | 有効なUTF-8データを含む String 要素。エスケープシーケンスは、アンエスケープ時に有効なUTF-8バイトシーケンスを形成する必要があります。 |
bytes | 無効なUTF-8エスケープシーケンスを含む可能性のある String 要素。 |
bool | 以下の値のいずれかに一致する Identifier 要素または unsignedInteger 要素。真値: "True", "true", "t", 1 偽値: "False", "false", "f", 0 0 または 1 の任意の符号なし整数表現が許可されます: 00, 0x0, 01, 0x1 など。 |
| enum 値 | enum 値名を含む Identifier 要素、または enum 値番号を含む範囲 -0x80000000 から 0x7FFFFFFF の任意の integer 要素。フィールドの enum 型定義のメンバーではない名前を指定することは無効です。特定の protobuf ランタイム実装によっては、フィールドの enum 型定義のメンバーではない番号を指定することが有効である場合とそうでない場合があります。特定のランタイム実装に縛られないテキスト形式プロセッサ (IDE サポートなど) は、提供された数値が有効なメンバーではない場合に警告を発することを選択できます。なお、_"true"_ や _"infinity"_ など、他のコンテキストでは有効なキーワードである特定の名前も、有効な enum 値名であることに注意してください。 |
| メッセージ値 | MessageValue 要素。 |
拡張フィールド
拡張フィールドは、その完全修飾名を使用して指定されます。例
local_field: 10
[com.example.ext_field]: 20
拡張フィールドは通常、他の .proto ファイルで定義されます。テキスト形式言語は、拡張フィールドを定義するファイルの場所を指定するメカニズムを提供しません。代わりに、パーサーはそれらの場所を事前に知っている必要があります。
Any フィールド
テキスト形式は、拡張フィールドに似た特殊な構文を使用して、google.protobuf.Any 既知の型の拡張形式をサポートしています。例
local_field: 10
# An Any value using regular fields.
any_value {
type_url: "type.googleapis.com/com.example.SomeType"
value: "\x0a\x05hello" # serialized bytes of com.example.SomeType
}
# The same value using Any expansion
any_value {
[type.googleapis.com/com.example.SomeType] {
field1: "hello"
}
}
この例では、any_value は google.protobuf.Any 型のフィールドであり、field1: hello を含むシリアライズされた com.example.SomeType メッセージを格納しています。
group フィールド
テキスト形式では、group フィールドはその値として通常の MessageValue 要素を使用しますが、暗黙的な小文字のフィールド名ではなく、大文字のグループ名を使用して指定されます。例
// proto2
message MessageWithGroup {
optional group MyGroup = 1 {
optional int32 my_value = 1;
}
}
上記の .proto 定義では、以下のテキスト形式が有効な MessageWithGroup となります。
MyGroup {
my_value: 1
}
メッセージフィールドと同様に、グループ名と値の間のデリミタ : はオプションです。
この機能は、下位互換性のためにエディションに含まれています。通常、DELIMITED フィールドは通常のメッセージのようにシリアライズされます。以下は、エディションでの動作を示しています。
edition = "2024";
message Parent {
message GroupLike {
int32 foo = 1;
}
GroupLike grouplike = 1 [features.message_encoding = DELIMITED];
}
その .proto ファイルの内容は proto2 グループのようにシリアライズされます。
GroupLike {
foo: 2;
}
map フィールド
テキスト形式では、マップフィールドエントリを指定するためのカスタム構文は提供されていません。マップフィールドが .proto ファイルで定義されている場合、key および value フィールドを含む暗黙的な Entry メッセージが定義されます。マップフィールドは常に繰り返し可能であり、複数のキー/値エントリを受け入れます。例
// Editions
edition = "2024";
message MessageWithMap {
map<string, int32> my_map = 1;
}
上記の .proto 定義では、以下のテキスト形式が有効な MessageWithMap となります。
my_map { key: "entry1" value: 1 }
my_map { key: "entry2" value: 2 }
# You can also use the list syntax
my_map: [
{ key: "entry3" value: 3 },
{ key: "entry4" value: 4 }
]
key フィールドと value フィールドはどちらもオプションであり、指定されていない場合はそれぞれの型のゼロ値にデフォルト設定されます。キーが重複している場合、解析されたマップには最後に指定された値のみが保持されます。
テキストプロトではマップの順序は維持されません。
oneof フィールド
テキスト形式には oneof フィールドに関連する特別な構文はありませんが、一度に1つの oneof メンバーのみを指定できます。複数のメンバーを同時に指定することは無効です。例
// Editions
edition = "2024";
message OneofExample {
message MessageWithOneof {
string not_part_of_oneof = 1;
oneof Example {
string first_oneof_field = 2;
string second_oneof_field = 3;
}
}
repeated MessageWithOneof message = 1;
}
上記の .proto 定義は、以下のテキスト形式の動作をもたらします。
# Valid: only one field from the Example oneof is set.
message {
not_part_of_oneof: "always valid"
first_oneof_field: "valid by itself"
}
# Valid: the other oneof field is set.
message {
not_part_of_oneof: "always valid"
second_oneof_field: "valid by itself"
}
# Invalid: multiple fields from the Example oneof are set.
message {
not_part_of_oneof: "always valid"
first_oneof_field: "not valid"
second_oneof_field: "not valid"
}
テキスト形式ファイル
テキスト形式ファイルは .txtpb というファイル名サフィックスを使用し、単一の Message を含みます。テキスト形式ファイルは UTF-8 でエンコードされます。テキストプロトファイルの例を以下に示します。
重要
.txtpb は正規のテキスト形式ファイル拡張子であり、他の選択肢よりも推奨されます。このサフィックスは、その簡潔さと公式のワイヤー形式ファイル拡張子 .binpb との一貫性から推奨されます。従来の正規拡張子 .textproto は依然として広く使用されており、ツールサポートもされています。一部のツールでは、従来の拡張子 .textpb および .pbtxt もサポートされています。上記の拡張子以外のすべての拡張子は**強く**非推奨です。特に、.protoascii などの拡張子は、テキスト形式がASCIIのみであると誤って示唆しており、.pb.txt などの拡張子は一般的なツールで認識されません。# This is an example of Protocol Buffer's text format.
# Unlike .proto files, only shell-style line comments are supported.
name: "John Smith"
pet {
kind: DOG
name: "Fluffy"
tail_wagginess: 0.65f
}
pet <
kind: LIZARD
name: "Lizzy"
legs: 4
>
string_value_with_escape: "valid \n escape"
repeated_values: [ "one", "two", "three" ]
ヘッダー
ヘッダーコメント proto-file および proto-message は、開発者ツールにスキーマを通知し、様々な機能を提供できるようにします。
# proto-file: some/proto/my_file.proto
# proto-message: MyMessage
プログラムによる形式の操作
個々のプロトコルバッファ実装が整合性のある正規のテキスト形式を出力しないため、TextProto ファイルを変更したり TextProto 出力を作成したりするツールやライブラリは、出力の形式設定のために https://github.com/protocolbuffers/txtpbfmt を明示的に使用する必要があります。