Dies ist eine Sprachspezifikationsreferenz für Version 2 der Protokollzwischenspeicher-Sprache (proto2). Die Syntax wird mit Extended Backus-Naur Form (EBNF) angegeben:
| alternation () grouping [] option (zero or one time) {} repetition (any number of times)
Weitere Informationen zur Verwendung von proto2 finden Sie im Sprachleitfaden.
Lexikalische Elemente
Buchstaben und Ziffern
letter = "A" … "Z" | "a" … "z" capitalLetter = "A" … "Z" decimalDigit = "0" … "9" octalDigit = "0" … "7" hexDigit = "0" … "9" | "A" … "F" | "a" … "f"
Kennungen
ident = letter { letter | decimalDigit | "_" } fullIdent = ident { "." ident } messageName = ident enumName = ident fieldName = ident oneofName = ident mapName = ident serviceName = ident rpcName = ident streamName = ident messageType = [ "." ] { ident "." } messageName enumType = [ "." ] { ident "." } enumName groupName = capitalLetter { letter | decimalDigit | "_" }
Ganzzahlliterale
intLit = decimalLit | octalLit | hexLit decimalLit = ( "1" … "9" ) { decimalDigit } octalLit = "0" { octalDigit } hexLit = "0" ( "x" | "X" ) hexDigit { hexDigit }
Gleitkommaliterale
floatLit = ( decimals "." [ decimals ] [ exponent ] | decimals exponent | "."decimals [ exponent ] ) | "inf" | "nan" decimals = decimalDigit { decimalDigit } exponent = ( "e" | "E" ) [ "+" | "-" ] decimals
Boolesch
boolLit = "true" | "false"
Stringliterale
strLit = ( "'" { charValue } "'" ) | ( '"' { charValue } '"' ) charValue = hexEscape | octEscape | charEscape | /[^\0\n\\]/ hexEscape = '\' ( "x" | "X" ) hexDigit hexDigit octEscape = '\' octalDigit octalDigit octalDigit charEscape = '\' ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | '\' | "'" | '"' )
Leere Aufstellung
emptyStatement = ";"
Konstante
constant = fullIdent | ( [ "-" | "+" ] intLit ) | ( [ "-" | "+" ] floatLit ) | strLit | boolLit
Syntax
Mit der Syntaxanweisung wird die Protobuf-Version definiert.
syntax = "syntax" "=" ("'" "proto2" "'" | '"' "proto2" '"') ";"
Importanweisung
Mit der Importanweisung werden die Definitionen einer anderen .proto-Datei importiert.
import = "import" [ "weak" | "public" ] strLit ";"
Beispiel:
import public "other.proto";
Paket
Mit dem Paketbezeichner können Namenskonflikte zwischen Protokollnachrichtentypen vermieden werden.
package = "package" fullIdent ";"
Beispiel:
package foo.bar;
Option
Optionen können in Proto-Dateien, Nachrichten, Enums und Diensten verwendet werden. Eine Option kann eine vom Protobuf definierte Option oder eine benutzerdefinierte Option sein. Weitere Informationen finden Sie im Leitfaden für die Sprache.
option = "option" optionName "=" constant ";" optionName = ( ident | "(" fullIdent ")" ) { "." ident }
Beispiele:
option java_package = "com.example.foo";
Felder
Felder sind die grundlegenden Elemente einer Protokollpuffernachricht. Felder können normale Felder, Gruppenfelder, einmalige Felder oder Zuordnungsfelder sein. Ein Feld hat ein Label, einen Typ und eine Feldnummer.
label = "required" | "optional" | "repeated" type = "double" | "float" | "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string" | "bytes" | messageType | enumType fieldNumber = intLit;
Normales Feld
Jedes Feld hat ein Label, einen Typ, einen Namen und eine Feldnummer. Er kann Feldoptionen enthalten.
field = label type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";" fieldOptions = fieldOption { "," fieldOption } fieldOption = optionName "=" constant
Beispiele:
optional foo.bar nested_message = 2; repeated int32 samples = 4 [packed=true];
Gruppenfeld
Beachten Sie, dass diese Funktion eingestellt wurde und nicht für neue Nachrichtentypen verwendet werden sollte. Verwenden Sie stattdessen verschachtelte Nachrichtentypen.
Gruppen sind eine Möglichkeit, Informationen in Nachrichtendefinitionen zu verschachteln. Der Gruppenname muss mit einem Großbuchstaben beginnen.
group = label "group" groupName "=" fieldNumber messageBody
Beispiel:
repeated group Result = 1 { required string url = 2; optional string title = 3; repeated string snippets = 4; }
Oneof- und Oneof-Feld
Eine davon besteht aus einem Feld und einem Namen. Eines der Felder hat keine Labels.
oneof = "oneof" oneofName "{" { option | oneofField | emptyStatement } "}" oneofField = type fieldName "=" fieldNumber [ "[" fieldOptions "]" ] ";"
Beispiel:
oneof foo { string name = 4; SubMessage sub_message = 9; }
Kartenfeld
Ein Zuordnungsfeld hat einen Schlüsseltyp, einen Werttyp, einen Namen und eine Feldnummer. Der Schlüsseltyp kann ein beliebiger Integral- oder Stringtyp sein. Der Schlüsseltyp ist möglicherweise kein Enum.
mapField = "map" "<" keyType "," type ">" mapName "=" fieldNumber [ "[" fieldOptions "]" ] ";" keyType = "int32" | "int64" | "uint32" | "uint64" | "sint32" | "sint64" | "fixed32" | "fixed64" | "sfixed32" | "sfixed64" | "bool" | "string"
Beispiel:
map<string, Project> projects = 3;
Erweiterungen und reserviert
Erweiterungen und reservierte Elemente sind Nachrichtenelemente, die einen Bereich von Feldnummern oder Feldnamen deklarieren.
Erweiterungen
Erweiterungen deklarieren, dass in einer Nachricht eine Reihe von Feldnummern für Erweiterungen von Drittanbietern verfügbar sind. Andere Nutzer können neue Felder für Ihren Nachrichtentyp mit diesen numerischen Tags in ihren eigenen .proto-Dateien deklarieren, ohne die ursprüngliche Datei bearbeiten zu müssen.
extensions = "extensions" ranges ";" ranges = range { "," range } range = intLit [ "to" ( intLit | "max" ) ]
Beispiele:
extensions 100 to 199; extensions 4, 20 to max;
Reserviert
Reserviert deklariert eine Reihe von Feldnummern oder Feldnamen in einer Nachricht, die nicht verwendet werden kann.
reserved = "reserved" ( ranges | strFieldNames ) ";" strFieldNames = strFieldName { "," strFieldName } strFieldName = "'" fieldName "'" | '"' fieldName '"'
Beispiele:
reserved 2, 15, 9 to 11; reserved "foo", "bar";
Definitionen der obersten Ebene
Enum-Definition
Die Enum-Definition besteht aus einem Namen und einem Enum-Text. Der Enum-Textkörper kann Optionen, Enumerationsfelder und reservierte Anweisungen enthalten.
enum = "enum" enumName enumBody enumBody = "{" { option | enumField | emptyStatement | reserved } "}" enumField = ident "=" [ "-" ] intLit [ "[" enumValueOption { "," enumValueOption } "]" ]";" enumValueOption = optionName "=" constant
Beispiel:
enum EnumAllowingAlias { option allow_alias = true; EAA_UNSPECIFIED = 0; EAA_STARTED = 1; EAA_RUNNING = 2 [(custom_option) = "hello world"]; }
Nachrichtendefinition
Eine Nachricht besteht aus einem Nachrichtennamen und einem Nachrichtentext. Der Nachrichtentext kann Felder, verschachtelte Enum-Definitionen, verschachtelte Nachrichtendefinitionen, Erweiterungsanweisungen, Erweiterungen, Gruppen, Optionen, Ones, Map-Felder und reservierte Anweisungen enthalten.
message = "message" messageName messageBody messageBody = "{" { field | enum | message | extend | extensions | group | option | oneof | mapField | reserved | emptyStatement } "}"
Beispiel:
message Outer { option (my_option).a = true; message Inner { // Level 2 required int64 ival = 1; } map<int32, string> my_map = 2; extensions 20 to 30; }
Erweiterung
Wenn eine Nachricht in derselben oder importierten .proto-Datei einen Bereich für Erweiterungen reserviert hat, kann die Nachricht verlängert werden.
extend = "extend" messageType "{" {field | group | emptyStatement} "}"
Beispiel:
extend Foo { optional int32 bar = 126; }
Dienstdefinition
service = "service" serviceName "{" { option | rpc | stream | emptyStatement } "}" rpc = "rpc" rpcName "(" [ "stream" ] messageType ")" "returns" "(" [ "stream" ] messageType ")" (( "{" { option | emptyStatement } "}" ) | ";" ) stream = "stream" streamName "(" messageType "," messageType ")" (( "{" { option | emptyStatement } "}") | ";" )
Beispiel:
service SearchService { rpc Search (SearchRequest) returns (SearchResponse); }
.proto-Datei
proto = syntax { import | package | option | topLevelDef | emptyStatement } topLevelDef = message | enum | extend | service
Eine .proto-Beispieldatei:
syntax = "proto2"; import public "other.proto"; option java_package = "com.example.foo"; enum EnumAllowingAlias { option allow_alias = true; EAA_UNSPECIFIED = 0; EAA_STARTED = 1; EAA_RUNNING = 1; EAA_FINISHED = 2 [(custom_option) = "hello world"]; } message Outer { option (my_option).a = true; message Inner { // Level 2 required int64 ival = 1; } repeated Inner inner_message = 2; optional EnumAllowingAlias enum_field = 3; map<int32, string> my_map = 4; extensions 20 to 30; } message Foo { optional group GroupMessage = 1 { optional bool a = 1; } }