テキスト形式言語仕様
この形式は、例えば .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) を消費してバイト値 0x83 (ASCII ‘S’) をアンエスケープし、後続の ‘4’ はバイト値 0x34 (ASCII ‘4’) としてそのまま渡されます。正しくパースするために、8 進数エスケープシーケンスは、必要に応じて先頭にゼロを使用して、3 桁の 8 進数で表現してください (例: \000
、\001
、\063
、\377
)。数値以外の文字が数値文字の後に続く場合 (例: \5Hello
) は、3 桁未満が消費されます。
16 進数エスケープシーケンスは、最大 2 桁の 16 進数を消費します。例えば、\x213
をアンエスケープする場合、パーサーは最初の 2 桁 (21) のみ消費してバイト値 0x21 (ASCII ‘!’) をアンエスケープします。正しくパースするために、16 進数エスケープシーケンスは、必要に応じて先頭にゼロを使用して、2 桁の 16 進数で表現してください (例: \x00
、\x01
、\xFF
)。16 進数以外の文字が数値文字の後に続く場合 (例: \xFHello
や \x3world
) は、2 桁未満が消費されます。
バイト単位のエスケープは、型が bytes
のフィールドに対してのみ使用してください。型が string
のフィールドでバイト単位のエスケープを使用することも可能ですが、それらのエスケープシーケンスは有効な UTF-8 シーケンスを形成する必要があります。UTF-8 シーケンスを表現するためにバイト単位のエスケープを使用すると、エラーが発生しやすくなります。string
型フィールドのリテラルでは、印刷不可能な文字と改行文字にはユニコードエスケープシーケンスを使用することを推奨します。
長い文字列は、連続する行に複数の引用符付き文字列に分割できます。例
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 Table A-1 Extended 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
としてワイヤータイプが含まれているため、非可逆です。エンコーディングの詳細については、エンコーディング トピックを参照してください。
メッセージスキーマからのフィールドタイプに関する情報がないと、値をワイヤー形式の proto メッセージに正しくエンコードできません。
フィールド
フィールド値には、リテラル (文字列、数値、または識別子) またはネストされたメッセージを使用できます。
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
ではないフィールドは、リスト構文を使用できません。例えば、[0]
は optional
または required
フィールドに対して有効ではありません。optional
とマークされたフィールドは、省略するか、1 回指定できます。required
とマークされたフィールドは、正確に 1 回指定する必要があります。
関連付けられた .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 | String 要素。無効な UTF-8 エスケープシーケンスが含まれている可能性があります。 |
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 値の名前であることに注意してください。 |
message 値 | 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
要素を値として使用しますが、暗黙的な小文字のフィールド名ではなく、大文字のグループ名を使用して指定されます。例
message MessageWithGroup {
optional group MyGroup = 1 {
optional int32 my_value = 1;
}
}
上記の .proto 定義では、次のテキスト形式は有効な MessageWithGroup
です。
MyGroup {
my_value: 1
}
メッセージフィールドと同様に、グループ名と値の間の :
デリミターはオプションです。
map
フィールド
テキスト形式は、map フィールドエントリを指定するためのカスタム構文を提供していません。.proto ファイルで map
フィールドが定義されている場合、key
フィールドと value
フィールドを含む暗黙的な Entry
メッセージが定義されます。Map フィールドは常に repeated であり、複数のキー/値エントリを受け入れます。例
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
フィールドはどちらもオプションであり、指定されていない場合はそれぞれの型のゼロ値にデフォルト設定されます。キーが重複している場合、パースされた map では最後に指定された値のみが保持されます。
map の順序は textproto では維持されません。
oneof
フィールド
テキスト形式の oneof
フィールドに関連する特別な構文はありませんが、一度に指定できる oneof
メンバーは 1 つだけです。複数のメンバーを同時に指定することは無効です。例
message OneofExample {
message MessageWithOneof {
optional 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
プログラムによる形式の操作
個々の Protocol Buffer 実装が一貫性のある正規のテキスト形式を出力しないため、TextProto ファイルを変更したり、TextProto 出力を出力したりするツールまたはライブラリは、出力をフォーマットするために https://github.com/protocolbuffers/txtpbfmt を明示的に使用する必要があります。