FIDL: Language Specification

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.

Syntax

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.

Tokens

Comments

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!

Document Comments

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.

Reserved Words

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”.

Identifiers

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 { };

Qualified Identifiers

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;
    };

Literals

FIDL supports the following literal types using C-like syntax: bools, signed integers, unsigned integers, floats, strings.

    const bool kBool = true;
    const int32 kInt = -333;
    const uint32 kUInt = 42;
    const uint64 kDiamond = 0x183c7effff7e3c18;
    const string kString = "a string";
    const float32 kFloat = 1.0;

Declaration Separator

FIDL uses the semi-colon ‘;’ to separate adjacent declarations within the file, much like C.

Libraries

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 “mozart.composition” within the C++ namespace “mozart::composition”. 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.

Types and Type Declarations

Primitives

  • Simple value types.
  • Not nullable.

The following primitive types are supported:

  • Boolean bool
  • Signed integer int8 int16 int32 int64
  • Unsigned integer uint8 uint16 uint32 uint64
  • IEEE 754 Floating-point float32 float64

Numbers are suffixed with their size in bits, bool is 1 byte.

Use
// A record which contains fields of a few primitive types.
struct Sprite {
    float32 x;
    float32 y;
    uint32 index;
    uint32 color;
    bool visible;
};

Enums

  • Proper enumerated types; bit fields are not valid enums.
  • Discrete subset of named values chosen from an underlying integer primitive type.
  • Not nullable.
  • Enums must have at least one member.
Declaration

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;
};
Use

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

  • Fixed-length sequences of homogeneous elements.
  • Elements can be of any type including: primitives, enums, arrays, strings, vectors, handles, structs, unions.
  • Not nullable themselves; may contain nullable types.
Use

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;
};

Strings

  • Variable-length sequence of UTF-8 encoded characters representing text.
  • Nullable; null strings and empty strings are distinct.
  • Can specify a maximum size, eg. string:40 for a maximum 40 byte string.
Use

Strings are denoted as follows:

  • string : non-nullable string (validation error occurs if null is encountered)
  • string? : nullable string
  • string: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;
};

Vectors

  • Variable-length sequence of homogeneous elements.
  • Nullable; null vectors and empty vectors are distinct.
  • Can specify a maximum size, eg. vector<T>:40 for a maximum 40 element vector.
  • There is no special case for vectors of bools. Each bool element takes one byte as usual.
Use

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 T
  • vector<T>:N, vector<T>:N? : vector with maximum length of N elements

T 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

  • Transfers a Zircon capability by handle value.
  • Stored as a 32-bit unsigned integer.
  • Nullable by encoding as a zero-valued handle.
Use

Handles are denoted:

  • handle : non-nullable Zircon handle of unspecified type
  • handle? : nullable Zircon handle of unspecified type
  • handle<H> : non-nullable Zircon handle of type H
  • handle<H>? : nullable Zircon handle of type H

H 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;
};

Structs

  • Record type consisting of a sequence of typed fields.
  • Declaration is not intended to be modified once deployed; use interface extension instead.
  • Reference may be nullable.
  • Structs contain one or more members. A struct with no members is difficult to represent in C and C++ as a zero-sized type. Fidl therefore chooses to require all structs to have nonzero size.
Declaration
struct Point {
    float32 x;
    float32 y;
};
struct Color {
    float32 r;
    float32 g;
    float32 b;
};

Use

Structs are denoted by their declared name (eg. Circle) and nullability:

  • Circle : non-nullable Circle
  • Circle? : nullable Circle
struct Circle {
    bool filled;
    Point center;    // Point will be stored in-line
    float32 radius;
    Color? color;    // Color will be stored out-of-line
    bool dashed;
};

Unions

  • Tagged option type consisting of tag field and variadic contents.
  • Declaration is not intended to be modified once deployed; use interface extension instead.
  • Reference may be nullable.
  • Unions contain one or more members. A union with no members would have no inhabitants and make little sense in a wire format.
Declaration
union Pattern {
    Color color;
    Texture texture;
};
struct Color {
    float32 r;
    float32 g;
    float32 b;
};
struct Texture { string name; };
Use

Union are denoted by their declared name (eg. Pattern) and nullability:

  • Pattern : non-nullable Shape
  • Pattern? : nullable Shape
struct Paint {
    Pattern fg;
    Pattern? bg;
};

Interfaces

  • Describe methods which can be invoked by sending messages over a channel.
  • Methods are identified by their ordinal index. Ordinals must be stated explicitly to reduce the chance that developers might break interfaces by reordering methods and to help with interface extension and derivation.
    • Method ordinals are unsigned values in the range 0x00000001 to 0x7fffffff.
    • The FIDL wire format internally represents ordinals as 32-bit values but reserves the range 0x80000000 to 0xffffffff for protocol control messages, so these values cannot be associated with methods.
  • Each method declaration states its arguments and results.
    • If no results are declared, then the method is one-way: no response will be generated by the server.
    • If results are declared (even if empty), then the method is two-way: each invocation of the method generates a response from the server.
    • If only results are declared, the method is referred to as an event. It then defines an unsolicited message from the server.
  • When a client or server of an interface is about to close its side of the channel, it may elect to send an epitaph message to its peer to indicate the disposition of the connection. If sent, the epitaph must be the last message delivered through the channel. An epitaph message includes:
    • 32-bit generic status: one of the ZX_status_t constants
    • 32-bit protocol-specific code: meaning is left up to the interface in question
    • a string: a human-readable message explaining the disposition
  • Interface extension: New methods can be added to existing interfaces as long as they do not collide with existing methods.
  • Interface derivation: New interfaces can be derived from any number of existing interfaces as long as none of their methods use the same ordinals. (This is purely a FIDL language feature, does not affect the wire format.)
Declaration
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);
};
Use

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

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 kFavoriteNumber = 42;

Constant Expressions

Constant expressions are either literals or the names of other constant expressions.

Grammar

A modified EBNF description of the fidl grammar is here.