This document is a specification of the Fuchsia Interface Definition Language (FIDL) syntax.
See FIDL: Overview for more information about FIDL's overall purpose, goals, and requirements, as well as links to related documents.
The Fuchsia Interface Definition Language provides a syntax for declaring named constants, enums, structs, unions, and interfaces. These declarations are collected into libraries for distribution.
FIDL declarations are stored in plain text UTF-8 files. Each file consists of a sequence of semicolon delimited declarations. The order of declarations within a FIDL file or among FIDL files within a library is irrelevant. FIDL does not require (or support) forward declarations of any kind.
FIDL supports C++-style comments. These go from //
to the end of the line. They may contain UTF-8 content (which is of course ignored).
// this is a comment struct Foo { // so is this int32 f; // and this }; // last one!
TODO(TO-504): We will generate online documentation from FIDL files. Perhaps the compiler can emit document contents together with the declarations in a machine-readable FIDL IR format that could be consumed by other tools.
The following keywords are reserved in FIDL.
array, as, bool, const, enum, float32, float64, handle, int8, int16, int32, int64, interface, library, request, string, struct, uint8, uint16, uint32, uint64, union, using, vector
To use these words as identifiers, they must be escaped by prepending an “@”. For example “interface” is a reserved word but “@interface” is an identifier whose name is “interface”.
FIDL identifiers must match the regex “@?[a-zA-Z_][0-9a-zA-Z]*”. The “@” prefix, if present, serves to distinguish identifiers from reserved words in the FIDL language. The “@” prefix itself is ignored for the purposes of naming the identifier. This allows reserved words in the FIDL language to nevertheless be used as identifiers (when escaped with “@”).
Identifiers are case-sensitive.
// a library named "foo" library foo; // a struct named "Foo" struct Foo { }; // a struct named "struct" struct @struct { };
FIDL always looks for unqualified symbols within the scope of the current library. To reference symbols in other libraries, they must be qualified by prefixing the identifier with the library name or alias.
objects.fidl:
library objects; using textures as tex; interface Frob { // "Thing" refers to "Thing" in the "objects" library // "tex.Color" refers to "Color" in the "textures" library Paint(Thing thing, tex.Color color); }; struct Thing { string name; };
textures.fidl:
library textures; struct Color { uint32 rgba; };
FIDL supports the following literal types using C-like syntax: bools, signed integers, unsigned integers, floats, strings.
const bool BOOL = true; const int32 INT = -333; const uint32 UINT = 42; const uint64 DIAMOND = 0x183c7effff7e3c18; const string STRING = "a string"; const float32 FLOAT = 1.0;
FIDL uses the semi-colon ‘;’ to separate adjacent declarations within the file, much like C.
Libraries are named containers of FIDL declarations.
Each library has a name consisting of a dot-delimited identifier. Library names appear in Qualified Identifiers.
Libraries may declare that they use other libraries with a “using” declaration. This allows the library to refer to symbols defined in other libraries upon which they depend. Symbols which are imported this way may be accessed either by qualifying them with the library name as in “mozart.geometry.Rect” or by qualifying them with the library alias as in “geo.Rect”.
library mozart.composition; using mozart.geometry as geo; using mozart.buffers; interface Compositor { … };
In the source tree, each library consists of a directory with some number of .fidl files. The name of the directory is irrelevant to the FIDL compiler but by convention it should resemble the library name itself. A directory should not contain FIDL files for more than one library.
The scope of “library” and “using” declarations is limited to a single file. Each individual file within a FIDL library must restate the “library” declaration together with any “using” declarations needed by that file.
The library's name may be used by certain language bindings to provide scoping for symbols emitted by the code generator.
For example, the C++ bindings generator places declarations for the FIDL library “fuchsia.ui” within the C++ namespace “fuchsia::ui”. Similarly, for languages such as Dart and Rust which have their own module system, each FIDL library is compiled as a module for that language.
The following primitive types are supported:
bool
int8 int16 int32 int64
uint8 uint16 uint32 uint64
float32 float64
Numbers are suffixed with their size in bits, bool
is 1 byte.
// A record which contains fields of a few primitive types. struct Sprite { float32 x; float32 y; uint32 index; uint32 color; bool visible; };
The ordinal index is required for each enum element. The underlying type of an enum must be one of: int8, uint8, int16, uint16, int32, uint32, int64, uint64. If omitted, the underlying type is assumed to be uint32.
// An enum declared at library scope. enum Beverage : uint8 { WATER = 0; COFFEE = 1; TEA = 2; WHISKEY = 3; }; // An enum declared at library scope. // Underlying type is assumed to be uint32. enum Vessel { CUP = 0; BOWL = 1; TUREEN = 2; JUG = 3; };
Enum types are denoted by their identifier, which may be qualified if needed.
// A record which contains two enum fields. struct Order { Beverage beverage; Vessel vessel; };
Arrays are denoted array<T>:n
where T can be any FIDL type (including an array) and n is a positive integer constant expression which specified the number of elements in the array.
// A record which contains some arrays. struct Record { // array of exactly 16 floating point numbers array<float32>:16 matrix; // array of exactly 10 arrays of 4 strings each array<array<string>:4>:10 form; };
string:40
for a maximum 40 byte string.Strings are denoted as follows:
string
: non-nullable string (validation error occurs if null is encountered)string?
: nullable stringstring:N, string:N?
: string with maximum length of N bytes// A record which contains some strings. struct Record { // title string, maximum of 40 bytes long string:40 title; // description string, may be null, no upper bound on size string? description; };
vector<T>:40
for a maximum 40 element vector.Vectors are denoted as follows:
vector<T>
: non-nullable vector of element type T (validation error occurs if null is encountered)vector<T>?
: nullable vector of element type Tvector<T>:N, vector<T>:N?
: vector with maximum length of N elementsT can be any FIDL type.
// A record which contains some vectors. struct Record { // a vector of up to 10 integers vector<int32>:10 params; // a vector of bytes, no upper bound on size vector<uint8> blob; // a nullable vector of up to 24 strings vector<string>:24? nullable_vector_of_strings; // a vector of nullable strings vector<string?> vector_of_nullable_strings; // a vector of vectors of arrays of floating point numbers vector<vector<array<float32>:16>> complex; };
Handles are denoted:
handle
: non-nullable Zircon handle of unspecified typehandle?
: nullable Zircon handle of unspecified typehandle<H>
: non-nullable Zircon handle of type Hhandle<H>?
: nullable Zircon handle of type HH can be one of: channel, event, eventpair, fifo, job, process, port, resource, socket, thread, vmo
. New types will be added to the fidl language as they are added to Zircon.
// A record which contains some handles. struct Record { // a handle of unspecified type handle h; // an optional channel handle<channel>? c; };
struct Point { float32 x; float32 y; }; struct Color { float32 r; float32 g; float32 b; };
Structs are denoted by their declared name (eg. Circle) and nullability:
Circle
: non-nullable CircleCircle?
: nullable Circlestruct Circle { bool filled; Point center; // Point will be stored in-line float32 radius; Color? color; // Color will be stored out-of-line bool dashed; };
union Pattern { Color color; Texture texture; }; struct Color { float32 r; float32 g; float32 b; }; struct Texture { string name; };
Union are denoted by their declared name (eg. Pattern) and nullability:
Pattern
: non-nullable ShapePattern?
: nullable Shapestruct Paint { Pattern fg; Pattern? bg; };
interface Calculator { 1: Add(int32 a, int32 b) -> (int32 sum); 2: Divide(int32 dividend, int32 divisor) -> (int32 quotient, int32 remainder); 3: Clear(); 4: -> OnClear(); }; interface RealCalculator : Calculator { 1001: AddFloats(float32 a, float32 b) -> (float32 sum); }; interface Science { 2001: Hypothesize(); 2002: Investigate(); 2003: Explode(); 2004: Reproduce(); }; interface ScientificCalculator : RealCalculator, Science { 3001: Sin(float32 x) -> (float32 result); };
Interfaces are denoted by their name, directionality of the channel, and optionality:
Interface
: non-nullable FIDL interface (client endpoint of channel)Interface?
: nullable FIDL interface (client endpoint of channel)request<Interface>
: non-nullable FIDL interface request (server endpoint of channel)request<Interface>?
: nullable FIDL interface request (server endpoint of channel)// A record which contains interface-bound channels. struct Record { // client endpoint of a channel bound to the Calculator interface Calculator c; // server endpoint of a channel bound to the Science interface request<Science> s; // optional client endpoint of a channel bound to the // RealCalculator interface RealCalculator? r; };
Constant declarations introduce a name within their scope. The constant's type must be either a primitive or an enum.
// a constant declared at library scope const int32 FAVORITE_NUMBER = 42;
Constant expressions are either literals or the names of other constant expressions.
A modified EBNF description of the fidl grammar is here.