テキストフォーマット言語仕様
このフォーマットは、例えば .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’) としてそのまま通過します。正しいパースを確実にするため、8進エスケープシーケンスは、必要に応じて先行ゼロを使用し、3桁の8進数字で表現してください。例えば、\000
, \001
, \063
, \377
のようにします。\5Hello
のように、数値文字の後に非数値文字が続く場合、3桁未満の数字が消費されます。
16進エスケープシーケンスは、最大2桁の16進数字を消費します。例えば、\x213
をアンエスケープする場合、パーサーは最初の2桁 (21) のみを消費してバイト値 0x21 (ASCII ‘!’) をアンエスケープします。正しいパースを確実にするため、16進エスケープシーケンスは、必要に応じて先行ゼロを使用し、2桁の16進数字で表現してください。例えば、\x00
, \x01
, \xFF
のようにします。\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 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 | 無効な UTF-8 エスケープシーケンスを含む可能性がある String 要素。 |
bool | 以下の値のいずれかに一致する Identifier 要素、または unsignedInteger 要素のいずれか。真値: "True", "true", "t", 1 偽値: "False", "false", "f", 0 0 または 1 の任意の符号なし整数表現が許可されます: 00, 0x0, 01, 0x1 など。 |
enum 値 | enum 値名を含む Identifier 要素、または -0x80000000 から 0x7FFFFFFF の範囲で enum 値番号を含む 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
要素を使用しますが、暗黙的な小文字のフィールド名ではなく、大文字のグループ名を使用して指定されます。例
message MessageWithGroup {
optional group MyGroup = 1 {
optional int32 my_value = 1;
}
}
上記の .proto 定義では、以下のテキストフォーマットは有効な MessageWithGroup
です
MyGroup {
my_value: 1
}
メッセージフィールドと同様に、グループ名と値の間の :
区切り文字はオプションです。
map
フィールド
テキストフォーマットは、マップフィールドのエントリを指定するためのカスタム構文を提供しません。.proto ファイルで map
フィールドが定義されている場合、key
と value
フィールドを含む暗黙的な Entry
メッセージが定義されます。マップフィールドは常に繰り返し可能であり、複数のキー/値エントリを受け入れます。例
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
フィールドに関連する特別な構文はありませんが、一度に指定できる 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 を使用して出力をフォーマットする必要があります。