blob: 456b777d66efcf4b2e948012356c26fc01b2c4cd [file] [log] [blame] [view]
Roger Meierc5026aa2015-02-09 12:03:59 +01001## Thrift interface description language
James E. King III234fb472019-01-13 23:19:18 -05002
Jens Geyerc75646a2022-08-30 22:54:32 +02003For Thrift version 0.18.0.
James E. King III234fb472019-01-13 23:19:18 -05004
Roger Meierc5026aa2015-02-09 12:03:59 +01005The Thrift interface definition language (IDL) allows for the definition of [Thrift Types](/docs/types). A Thrift IDL file is processed by the Thrift code generator to produce code for the various target languages to support the defined structs and services in the IDL file.
6
7## Description
8
Roger Meierc5026aa2015-02-09 12:03:59 +01009Here is a description of the Thrift IDL.
10
11## Document
12
13Every Thrift document contains 0 or more headers followed by 0 or more definitions.
14
15 [1] Document ::= Header* Definition*
16
17## Header
18
19A header is either a Thrift include, a C++ include, or a namespace declaration.
20
21 [2] Header ::= Include | CppInclude | Namespace
22
23### Thrift Include
24
25An include makes all the symbols from another file visible (with a prefix) and adds corresponding include statements into the code generated for this Thrift document.
26
27 [3] Include ::= 'include' Literal
28
29### C++ Include
30
31A C++ include adds a custom C++ include to the output of the C++ code generator for this Thrift document.
32
33 [4] CppInclude ::= 'cpp_include' Literal
34
35### Namespace
36
37A namespace declares which namespaces/package/module/etc. the type definitions in this file will be declared in for the target languages. The namespace scope indicates which language the namespace applies to; a scope of '*' indicates that the namespace applies to all target languages.
38
James E. King III234fb472019-01-13 23:19:18 -050039 [5] Namespace ::= ( 'namespace' ( NamespaceScope Identifier ) )
Roger Meierc5026aa2015-02-09 12:03:59 +010040
Jens Geyer56700e42020-02-22 16:51:51 +010041 [6] NamespaceScope ::= '*' | 'c_glib' | 'cpp' | 'delphi' | 'haxe' | 'go' | 'java' | 'js' | 'lua' | 'netstd' | 'perl' | 'php' | 'py' | 'py.twisted' | 'rb' | 'st' | 'xsd'
Roger Meierc5026aa2015-02-09 12:03:59 +010042
43## Definition
44
Triton Circonflexe4959a922022-06-07 21:40:41 +020045 [7] Definition ::= Const | Typedef | Enum | Struct | Union | Exception | Service
Roger Meierc5026aa2015-02-09 12:03:59 +010046
47### Const
48
49 [8] Const ::= 'const' FieldType Identifier '=' ConstValue ListSeparator?
50
51### Typedef
52
53A typedef creates an alternate name for a type.
54
55 [9] Typedef ::= 'typedef' DefinitionType Identifier
56
57### Enum
58
59An enum creates an enumerated type, with named values. If no constant value is supplied, the value is either 0 for the first element, or one greater than the preceding value for any subsequent element. Any constant value that is supplied must be non-negative.
60
61 [10] Enum ::= 'enum' Identifier '{' (Identifier ('=' IntConstant)? ListSeparator?)* '}'
62
Roger Meierc5026aa2015-02-09 12:03:59 +010063### Struct
64
65Structs are the fundamental compositional type in Thrift. The name of each field must be unique within the struct.
66
Triton Circonflexe4959a922022-06-07 21:40:41 +020067 [11] Struct ::= 'struct' Identifier 'xsd_all'? '{' Field* '}'
Roger Meierc5026aa2015-02-09 12:03:59 +010068
69N.B.: The `xsd_all` keyword has some purpose internal to Facebook but serves no purpose in Thrift itself. Use of this feature is strongly discouraged
70
71### Union
72
Jens Geyerfe9222a2016-03-24 00:33:06 +020073Unions are similar to structs, except that they provide a means to transport exactly one field of a possible set of fields, just like union {} in C++. Consequently, union members are implicitly considered optional (see requiredness).
Roger Meierc5026aa2015-02-09 12:03:59 +010074
Triton Circonflexe4959a922022-06-07 21:40:41 +020075 [12] Union ::= 'union' Identifier 'xsd_all'? '{' Field* '}'
Roger Meierc5026aa2015-02-09 12:03:59 +010076
77N.B.: The `xsd_all` keyword has some purpose internal to Facebook but serves no purpose in Thrift itself. Use of this feature is strongly discouraged
78
79### Exception
80
81Exceptions are similar to structs except that they are intended to integrate with the native exception handling mechanisms in the target languages. The name of each field must be unique within the exception.
82
Triton Circonflexe4959a922022-06-07 21:40:41 +020083 [13] Exception ::= 'exception' Identifier '{' Field* '}'
Roger Meierc5026aa2015-02-09 12:03:59 +010084
85### Service
86
87A service provides the interface for a set of functionality provided by a Thrift server. The interface is simply a list of functions. A service can extend another service, which simply means that it provides the functions of the extended service in addition to its own.
88
Triton Circonflexe4959a922022-06-07 21:40:41 +020089 [14] Service ::= 'service' Identifier ( 'extends' Identifier )? '{' Function* '}'
Roger Meierc5026aa2015-02-09 12:03:59 +010090
91## Field
92
Triton Circonflexe4959a922022-06-07 21:40:41 +020093 [15] Field ::= FieldID? FieldReq? FieldType Identifier ('=' ConstValue)? XsdFieldOptions ListSeparator?
Roger Meierc5026aa2015-02-09 12:03:59 +010094
95### Field ID
96
Triton Circonflexe4959a922022-06-07 21:40:41 +020097 [16] FieldID ::= IntConstant ':'
Roger Meierc5026aa2015-02-09 12:03:59 +010098
99### Field Requiredness
100
PoojaChandak20205b82020-11-06 11:33:40 +0100101There are two explicit requiredness values, and a third one that is applied implicitly if neither *required* nor *optional* are given: *default* requiredness.
Jens Geyerfe9222a2016-03-24 00:33:06 +0200102
Triton Circonflexe4959a922022-06-07 21:40:41 +0200103 [17] FieldReq ::= 'required' | 'optional'
Jens Geyerfe9222a2016-03-24 00:33:06 +0200104
105The general rules for requiredness are as follows:
106
107#### required
108
109- Write: Required fields are always written and are expected to be set.
110- Read: Required fields are always read and are expected to be contained in the input stream.
111- Defaults values: are always written
112
113If a required field is missing during read, the expected behaviour is to indicate an unsuccessful read operation to the caller, e.g. by throwing an exception or returning an error.
114
115Because of this behaviour, required fields drastically limit the options with regard to soft versioning. Because they must be present on read, the fields cannot be deprecated. If a required field would be removed (or changed to optional), the data are no longer compatible between versions.
116
117#### optional
118
119- Write: Optional fields are only written when they are set
120- Read: Optional fields may, or may not be part of the input stream.
121- Default values: are written when the isset flag is set
122
Pure Whited4c6b562019-10-09 05:59:10 +0800123Most language implementations use the recommended practice of so-called "isset" flags to indicate whether a particular optional field is set or not. Only fields with this flag set are written, and conversely the flag is only set when a field value has been read from the input stream.
Jens Geyerfe9222a2016-03-24 00:33:06 +0200124
125#### default requiredness (implicit)
126
127- Write: In theory, the fields are always written. There are some exceptions to that rule, see below.
128- Read: Like optional, the field may, or may not be part of the input stream.
129- Default values: may not be written (see next section)
130
Chad Knight6e1606a2018-05-10 12:58:24 -0500131Default requiredness is a good starting point. The desired behaviour is a mix of optional and required, hence the internal name "opt-in, req-out". Although in theory these fields are supposed to be written ("req-out"), in reality unset fields are not always written. This is especially the case, when the field contains a <null> value, which by definition cannot be transported through thrift. The only way to achieve this is by not writing that field at all, and that's what most languages do.
Jens Geyerfe9222a2016-03-24 00:33:06 +0200132
133#### Semantics of Default Values
134
135There are ongoing discussions about that topic, see JIRA for details. Not all implementations treat default values in the very same way, but the current status quo is more or less that default fields are typically set at initialization time. Therefore, a value that equals the default may not be written, because the read end will set the value implicitly. On the other hand, an implementation is free to write the default value anyways, as there is no hard restriction that prevents this.
136
137The major point to keep in mind here is the fact, that any unwritten default value implicitly becomes part of the interface version. If that default is changed, the interface changes. If, in contrast, the default value is written into the output data, the default in the IDL can change at any time without affecting serialized data.
Roger Meierc5026aa2015-02-09 12:03:59 +0100138
139### XSD Options
140
PoojaChandak20205b82020-11-06 11:33:40 +0100141N.B.: These have some internal purpose at Facebook but serve no current purpose in Thrift. The use of these options is strongly discouraged.
Roger Meierc5026aa2015-02-09 12:03:59 +0100142
Triton Circonflexe4959a922022-06-07 21:40:41 +0200143 [18] XsdFieldOptions ::= 'xsd_optional'? 'xsd_nillable'? XsdAttrs?
Roger Meierc5026aa2015-02-09 12:03:59 +0100144
Triton Circonflexe4959a922022-06-07 21:40:41 +0200145 [19] XsdAttrs ::= 'xsd_attrs' '{' Field* '}'
Roger Meierc5026aa2015-02-09 12:03:59 +0100146
147## Functions
148
Triton Circonflexe4959a922022-06-07 21:40:41 +0200149 [20] Function ::= 'oneway'? FunctionType Identifier '(' Field* ')' Throws? ListSeparator?
Roger Meierc5026aa2015-02-09 12:03:59 +0100150
Triton Circonflexe4959a922022-06-07 21:40:41 +0200151 [21] FunctionType ::= FieldType | 'void'
Roger Meierc5026aa2015-02-09 12:03:59 +0100152
Triton Circonflexe4959a922022-06-07 21:40:41 +0200153 [22] Throws ::= 'throws' '(' Field* ')'
Roger Meierc5026aa2015-02-09 12:03:59 +0100154
155## Types
156
Triton Circonflexe4959a922022-06-07 21:40:41 +0200157 [23] FieldType ::= Identifier | BaseType | ContainerType
Roger Meierc5026aa2015-02-09 12:03:59 +0100158
Triton Circonflexe4959a922022-06-07 21:40:41 +0200159 [24] DefinitionType ::= BaseType | ContainerType
Roger Meierc5026aa2015-02-09 12:03:59 +0100160
Triton Circonflexe4959a922022-06-07 21:40:41 +0200161 [25] BaseType ::= 'bool' | 'byte' | 'i8' | 'i16' | 'i32' | 'i64' | 'double' | 'string' | 'binary' | 'uuid'
Roger Meierc5026aa2015-02-09 12:03:59 +0100162
Triton Circonflexe4959a922022-06-07 21:40:41 +0200163 [26] ContainerType ::= MapType | SetType | ListType
Roger Meierc5026aa2015-02-09 12:03:59 +0100164
Triton Circonflexe4959a922022-06-07 21:40:41 +0200165 [27] MapType ::= 'map' CppType? '<' FieldType ',' FieldType '>'
Roger Meierc5026aa2015-02-09 12:03:59 +0100166
Triton Circonflexe4959a922022-06-07 21:40:41 +0200167 [28] SetType ::= 'set' CppType? '<' FieldType '>'
Roger Meierc5026aa2015-02-09 12:03:59 +0100168
Jens Geyer0d776642022-09-14 08:54:37 +0200169 [29] ListType ::= 'list' CppType? '<' FieldType '>'
Roger Meierc5026aa2015-02-09 12:03:59 +0100170
Triton Circonflexe4959a922022-06-07 21:40:41 +0200171 [30] CppType ::= 'cpp_type' Literal
Roger Meierc5026aa2015-02-09 12:03:59 +0100172
173## Constant Values
174
Triton Circonflexe4959a922022-06-07 21:40:41 +0200175 [31] ConstValue ::= IntConstant | DoubleConstant | Literal | Identifier | ConstList | ConstMap
Roger Meierc5026aa2015-02-09 12:03:59 +0100176
Triton Circonflexe4959a922022-06-07 21:40:41 +0200177 [32] IntConstant ::= ('+' | '-')? Digit+
Roger Meierc5026aa2015-02-09 12:03:59 +0100178
Triton Circonflexe4959a922022-06-07 21:40:41 +0200179 [33] DoubleConstant ::= ('+' | '-')? Digit* ('.' Digit+)? ( ('E' | 'e') IntConstant )?
Roger Meierc5026aa2015-02-09 12:03:59 +0100180
Triton Circonflexe4959a922022-06-07 21:40:41 +0200181 [34] ConstList ::= '[' (ConstValue ListSeparator?)* ']'
Roger Meierc5026aa2015-02-09 12:03:59 +0100182
Triton Circonflexe4959a922022-06-07 21:40:41 +0200183 [35] ConstMap ::= '{' (ConstValue ':' ConstValue ListSeparator?)* '}'
Roger Meierc5026aa2015-02-09 12:03:59 +0100184
185## Basic Definitions
186
187### Literal
188
Triton Circonflexe4959a922022-06-07 21:40:41 +0200189 [36] Literal ::= ('"' [^"]* '"') | ("'" [^']* "'")
Roger Meierc5026aa2015-02-09 12:03:59 +0100190
191### Identifier
192
Triton Circonflexe4959a922022-06-07 21:40:41 +0200193 [37] Identifier ::= ( Letter | '_' ) ( Letter | Digit | '.' | '_' )*
Roger Meierc5026aa2015-02-09 12:03:59 +0100194
Triton Circonflexe4959a922022-06-07 21:40:41 +0200195 [38] STIdentifier ::= ( Letter | '_' ) ( Letter | Digit | '.' | '_' | '-' )*
Roger Meierc5026aa2015-02-09 12:03:59 +0100196
197### List Separator
198
Triton Circonflexe4959a922022-06-07 21:40:41 +0200199 [39] ListSeparator ::= ',' | ';'
Roger Meierc5026aa2015-02-09 12:03:59 +0100200
201### Letters and Digits
202
Triton Circonflexe4959a922022-06-07 21:40:41 +0200203 [40] Letter ::= ['A'-'Z'] | ['a'-'z']
Roger Meierc5026aa2015-02-09 12:03:59 +0100204
Triton Circonflexe4959a922022-06-07 21:40:41 +0200205 [41] Digit ::= ['0'-'9']
Roger Meierc5026aa2015-02-09 12:03:59 +0100206
Jens Geyer83370692021-03-09 23:35:37 +0100207## Reserved keywords
208
209 "BEGIN", "END", "__CLASS__", "__DIR__", "__FILE__", "__FUNCTION__",
210 "__LINE__", "__METHOD__", "__NAMESPACE__", "abstract", "alias", "and", "args", "as",
211 "assert", "begin", "break", "case", "catch", "class", "clone", "continue", "declare",
212 "def", "default", "del", "delete", "do", "dynamic", "elif", "else", "elseif", "elsif",
213 "end", "enddeclare", "endfor", "endforeach", "endif", "endswitch", "endwhile", "ensure",
214 "except", "exec", "finally", "float", "for", "foreach", "from", "function", "global",
215 "goto", "if", "implements", "import", "in", "inline", "instanceof", "interface", "is",
216 "lambda", "module", "native", "new", "next", "nil", "not", "or", "package", "pass",
217 "public", "print", "private", "protected", "raise", "redo", "rescue", "retry", "register",
218 "return", "self", "sizeof", "static", "super", "switch", "synchronized", "then", "this",
219 "throw", "transient", "try", "undef", "unless", "unsigned", "until", "use", "var",
220 "virtual", "volatile", "when", "while", "with", "xor", "yield"
221
Roger Meierc5026aa2015-02-09 12:03:59 +0100222## Examples
223
224Here are some examples of Thrift definitions, using the Thrift IDL:
225
226 * [ThriftTest.thrift][] used by the Thrift TestFramework
227 * Thrift [tutorial][]
228 * Facebook's [fb303.thrift][]
229 * [Apache Cassandra's][] Thrift IDL: [cassandra.thrift][]
230 * [Evernote API][]
231
Robert Lua1390822018-12-27 23:57:35 +0800232 [ThriftTest.thrift]: https://raw.githubusercontent.com/apache/thrift/master/test/ThriftTest.thrift
Roger Meierc5026aa2015-02-09 12:03:59 +0100233 [tutorial]: /tutorial/
Robert Lua1390822018-12-27 23:57:35 +0800234 [fb303.thrift]: https://raw.githubusercontent.com/apache/thrift/master/contrib/fb303/if/fb303.thrift
Roger Meierc5026aa2015-02-09 12:03:59 +0100235 [Apache Cassandra's]: http://cassandra.apache.org/
Kengo Seki1c789ce2020-01-13 10:48:58 +0900236 [cassandra.thrift]: https://gitbox.apache.org/repos/asf?p=cassandra.git;a=blob_plain;f=interface/cassandra.thrift;hb=refs/heads/cassandra-3.0
237 [Evernote API]: https://github.com/evernote/evernote-thrift
Roger Meierc5026aa2015-02-09 12:03:59 +0100238
239## To Do/Questions
240
241Initialization of Base Types for all Languages?
242
243 * Do all Languages initialize them to 0, bool=false and string=""? or null, undefined?
244
245Why does position of `CppType` vary between `SetType` and `ListType`?
246
247 * std::set does sort the elements automatically, that's the design. see [Thrift Types](/docs/types) or the [C++ std:set reference][] for further details
PoojaChandak20205b82020-11-06 11:33:40 +0100248 * The question is, how other languages are doing that? What about custom objects, do they have a Compare function to set the order correctly?
Roger Meierc5026aa2015-02-09 12:03:59 +0100249
250 [C++ std:set reference]: http://www.cplusplus.com/reference/stl/set/
251
252Why can't `DefinitionType` be the same as `FieldType` (i.e. include `Identifier`)?
253
254Examine the `smalltalk.prefix` and `smalltalk.category` status (esp `smalltalk.category`, which takes `STIdentifier` as its argument)...
255
256What to do about `ListSeparator`? Do we really want to be as lax as we currently are?
257
258Should `Field*` really be `Field+` in `Struct`, `Enum`, etc.?
259