blob: 16b24c7be87a9d678648de595da85d917a205b91 [file] [log] [blame] [view]
# FIDL language specification
This document is a specification of the Fuchsia Interface Definition Language
(**FIDL**).
For more information about FIDL's overall purpose, goals, and requirements,
see [Overview][fidl-overview].
Also, see a modified [EBNF description of the FIDL grammar][fidl-grammar].
[TOC]
## Syntax
FIDL provides a syntax for declaring data types and protocols. These
declarations are collected into libraries for distribution.
FIDL declarations are stored in UTF-8 text 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.
### Comments
FIDL comments start with two forward slashes (`//`) and continue to the end of
the line. Comments that start with three forward slashes (`///`) are called
documentation comments, and get emitted as comments in the generated bindings.
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="comments" %}
```
### Keywords
The following words have special meaning in FIDL:
```
ajar, alias, as, bits, closed, compose, const, enum, error, false, flexible,
library, open, optional, protocol, resource, service, strict, struct, table,
true, type, union, using.
```
However, FIDL has no reserved keywords. For example:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="keywords" %}
```
### Identifiers {#identifiers}
#### Library names
FIDL _library names_ label [FIDL libraries](#libraries). They consist of one or
more components separated by dots (`.`). Each component must match the regex
`[a-z][a-z0-9]*`. In words: library name components must start with a lowercase
letter, can contain lowercase letters, and numbers.
```fidl
// A library named "foo".
library foo;
```
#### Identifiers
FIDL _identifiers_ label declarations and their members. They must match the
regex `[a-zA-Z]([a-zA-Z0-9_]*[a-zA-Z0-9])?`. In words: identifiers must start
with a letter, can contain letters, numbers, and underscores, but cannot end
with an underscore.
```fidl
// A struct named "Foo".
type Foo = struct {};
```
FIDL identifiers are case sensitive. However, identifiers must have unique
_canonical forms_, otherwise the FIDL compiler will fail with [fi-0035:
Canonical name collision](/reference/fidl/language/errcat#fi-0035). The
canonical form of an identifier is obtained by converting it to `snake_case`.
#### Qualified identifiers {#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 thereof.
**objects.fidl:**
```fidl
library objects;
using textures as tex;
protocol Frob {
// "Thing" refers to "Thing" in the "objects" library
// "tex.Color" refers to "Color" in the "textures" library
Paint(struct { thing Thing; color tex.Color; });
};
type Thing = struct {
name string;
};
```
**textures.fidl:**
```fidl
library textures;
type Color = struct {
rgba uint32;
};
```
#### Resolution algorithm {#resolution-algorithm}
FIDL uses the following algorithm to resolve identifiers. When a "try resolving"
step fails, it proceeds to the next step. When a "resolve" step fails, the
compiler produces an error.
* If it is unqualified:
1. Try resolving as a declaration in the current library.
2. Try resoving as a builtin declaration, e.g. `bool` refers to `fidl.bool`.
3. Resolve as a contextual bits/enum member, e.g. the `CHANNEL` in
`zx.handle:CHANNEL` refers to `zx.ObjType.Channel`.
* If it is qualified as `X.Y`:
1. Try resolving `X` as a declaration within the current library:
1. Resolve `Y` as a member of `X`.
2. Resolve `X` as a library name or alias.
1. Resolve `Y` as a declaration in `X`.
* If it is qualified as `x.Y.Z` where `x` represents one or more components:
1. Try resolving `x.Y` as a library name or alias:
1. Resolve `Z` as a declaration in `x.Y`.
2. Resolve `x` as a library name or alias:
1. Resolve `Y` as a declaration in `x`:
1. Resolve `Z` as a member of `x.Y`.
Note: If you import libraries `X` and `X.Y`, and library `X` defines an enum
named `Y`, you cannot refer to a member of that enum since `X.Y.Z` would be
interpreted as the declaration `Z` from library `X.Y`, even if no such
declaration exists. To refer to the enum member, you would have to remove or
alias one of the imports. This should not come up in practice when following the
[FIDL Style Guide][naming-style], which mandates `lowercase` library names and
`UpperCamel` declaration names.
#### Fully qualified names {#fqn}
FIDL uses fully qualified names (abbreviated "FQN") to refer unambiguously to
declarations and members. An FQN consts of a library name, a slash `/`, a
declaration identifier, and optionally a dot `.` and member identifier. For
example:
* `fuchsia.io/MAX_BUF` refers to the `MAX_BUF` constant in library `fuchsia.io`.
* `fuchsia.process/Launcher.Launch` refers to the `Launch` method in the
`Launcher` protocol of library `fuchsia.process`.
FQNs are used in error messages, in the FIDL JSON intermediate representation,
and in documentation comment cross references. They are also used as method
selectors, which method ordinals are derived from.
### Literals
FIDL supports the following kinds of literals:
* Boolean: `true`, `false`
* Integer: `0`, `-1`, `123`, `0xABC`, `0b101`, etc.
* Floating point: `1.23`, `-0.01`, `1e5`, `2.0e-3`, etc.
* String: `"hello"`, `"\\ \" \n \r \t \u{1f642}"`, etc.
### Constants {#constants}
FIDL allows defining constants for all types that support literals (boolean,
integer, floating point, and string), and bits and enums. For example:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="consts" %}
```
Constant expressions are either literals, references to other constants,
references to bits or enum members, or a combination of bits members separated
by the pipe character (`|`). FIDL does not support any other arithmetic
expressions such as `1 + 2`.
### Declaration separator
FIDL uses the semicolon (`;`) to separate adjacent declarations within the
file, much like C.
## Libraries {#libraries}
Libraries are named containers of FIDL declarations.
```fidl
// library identifier separated by dots
library fuchsia.composition;
// "using" to import library "fuchsia.mem"
using fuchsia.mem;
// "using" to import library "fuchsia.geometry" under the alias "geo"
using fuchsia.geometry as geo;
```
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 imported this way may be accessed by qualifying them
with the library name, as in `fuchsia.mem.Range`.
A `using` declaration can also specify an alias with the `as` syntax. In this
case, symbols in the other library can only be accessed by qualifying them with
the alias, as in `geo.Rect` (using `fuchsia.geometry.Rect` would not work).
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.
Libraries with multiple files [conventionally have an overview.fidl
file][library-overview] containing only a `library` declaration along with
attributes and a documentation comment.
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.
## Types and type declarations
FIDL supports a number of builtin types as well as declarations of new types
(e.g. structs, unions, type aliases) and protocols.
### Primitives
* Simple value types.
* Cannot be optional.
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, **`int8`** is 1 byte.
#### Use
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="primitives" %}
```
### Bits {#bits}
* Named bit types.
* Discrete subset of bit values chosen from an underlying integer type.
* Cannot be optional.
* Bits can either be [`strict` or `flexible`](#strict-vs-flexible).
* Bits default to `flexible`.
* `strict` bits must have at least one member (`flexible` bits can be empty).
#### Operators
`|` is the bitwise OR operator for bits.
#### Use
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="bits" %}
```
### Enums {#enums}
* Proper enumerated types.
* Discrete subset of named values chosen from an underlying integer type.
* Cannot be optional.
* Enums can be [`strict` or `flexible`](#strict-vs-flexible).
* Enums default to `flexible`.
* `strict` enums must have at least one member (`flexible` enums can be
memberless).
#### Declaration
The ordinal 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 defaults to **uint32**.
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="enums" %}
```
#### Use
Enum types are denoted by their identifier, which may be qualified if needed.
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="enum-use" %}
```
<<../../../development/languages/fidl/widgets/_enum.md>>
### Arrays
* Fixed-length sequences of homogeneous elements.
* Elements can be of any type.
* Cannot be optional themselves; may contain optional 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 that specifies the
number of elements in the array.
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="arrays" %}
```
Note that _N_ appears as a layout parameter, which means that it affects the ABI
of the type. In other words, changing the parameter `_N_` is an
[ABI-breaking][compat] change.
### Strings
* Variable-length sequence of UTF-8 encoded characters representing text.
* Can be optional; absent strings and empty strings are distinct.
* Can specify a maximum size, e.g. **`string:40`** for a maximum 40 byte
string. By default, `string` means `string:MAX`, i.e unbounded.
* String literals support the escape sequences `\\`, `\"`, `\n`, `\r`, `\t`,
and `\u{X}` where the `X` is 1 to 6 hex digits for a Unicode code point.
* May contain embedded `NUL` bytes, unlike traditional C strings.
#### Use
Strings are denoted as follows:
* **`string`** : required string ([validation error][lexicon-validate]
occurs if absent)
* **`string:optional`** : optional string
* **`string:N, string:<N, optional>`** : string, and optional string, respectively,
with maximum length of _N_ bytes
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="strings" %}
```
Note that _N_ appears as a constraint (it appears after the `:`), which means
that it does not affect the ABI of the type. In other words, changing the
parameter `_N_` is not an [ABI-breaking][compat] change.
> Strings should not be used to pass arbitrary binary data since bindings enforce
> valid UTF-8. Instead, consider `bytes` for small data or
> [`fuchsia.mem.Buffer`](/docs/development/api/fidl.md#consider-using-fuchsia_mem_buffer)
> for blobs. See
> [Should I use string or vector?](/docs/development/api/fidl.md#should-i-use-string-or-vector)
> for details.
### Vectors
* Variable-length sequence of homogeneous elements.
* Can be optional; absent vectors and empty vectors are distinct.
* Can specify a maximum size, e.g. **`vector<T>:40`** for a maximum 40 element
vector. By default, `vector<T>` means `vector<T>:MAX`, i.e. unbounded.
* 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>`** : required vector of element type
_T_ ([validation error][lexicon-validate] occurs if absent)
* **`vector<T>:optional`** : optional vector of element type
_T_
* **`vector<T>:N` and `vector<T>:<N, optional>`** : vector, and optional vector,
respectively, with maximum length of _N_ elements
_T_ can be any FIDL type.
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="vectors" %}
```
### Handles {#handles}
* Transfers a Zircon capability by handle value.
* Stored as a 32-bit unsigned integer.
* Can be optional; absent handles are encoded as a zero-valued handle.
* Handles may optionally be associated with a type and set of required Zircon
rights.
#### Use
Handles are denoted:
* **`zx.Handle`** : required Zircon handle of unspecified type
* **`zx.Handle:optional`** : optional Zircon handle of unspecified type
* **`zx.Handle:H`** : required Zircon handle of type _H_
* **`zx.Handle:<H, optional>`** : optional Zircon handle of type _H_
* **`zx.Handle:<H, R>`** : required Zircon handle of type _H_ with rights
_R_
* **`zx.Handle:<H, R, optional>`** : optional Zircon handle of type _H_ with
rights _R_
_H_ can be any [object](/docs/reference/kernel_objects/objects.md) supported by
Zircon, e.g. `channel`, `thread`, `vmo`. Please refer to the
[grammar](grammar.md) for a full list.
_R_ can be any [right](/docs/concepts/kernel/rights.md) supported by Zircon.
Rights are bits-typed values, defined in the [`zx`](/zircon/vdso/rights.fidl)
FIDL library, e.g. `zx.Rights.READ`. In both the incoming and outgoing
directions, handles are validated to have the correct Zircon object type and at
least as many rights as are specified in FIDL. If the handle has more rights
than is specified in FIDL, then its rights will be reduced by a call to
`zx_handle_replace`. See [Life of a handle] for an example and [RFC-0028: Handle
rights](/docs/contribute/governance/rfcs/0028_handle_rights.md) for further
details.
Structs, tables, and unions containing handles must be marked with the
[`resource` modifier](#value-vs-resource).
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="handles" %}
```
### Structs {#structs}
* Record type consisting of a sequence of typed fields.
* Adding or removing fields or changing their types is generally
not ABI compatible.
* Declaration can have the [`resource` modifier](#value-vs-resource).
* References may be `box`ed.
* Structs contain zero or more members.
#### Declaration
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="structs" %}
```
#### Use
Structs are denoted by their declared name (e.g. **Circle**):
* **`Circle`** : required Circle
* **`box<Circle>`** : optional Circle, stored [out-of-line][wire-format].
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="structs-use" %}
```
### Tables {#tables}
* Record type consisting of a sequence of typed fields with ordinals.
* Declaration is intended for forward and backward compatibility in the face of schema changes.
* Declaration can have the [`resource` modifier](#value-vs-resource).
* Tables cannot be optional. The semantics of "missing value" is expressed by an empty table
i.e. where all members are absent, to avoid dealing with double optionality.
* Tables contain zero or more members.
#### Declaration
```fidl
type Profile = table {
1: locales vector<string>;
2: calendars vector<string>;
3: time_zones vector<string>;
};
```
#### Use
Tables are denoted by their declared name (e.g. **Profile**):
* **`Profile`** : required Profile
Here, we show how `Profile` evolves to also carry temperature units.
A client aware of the previous definition of `Profile` (without temperature units)
can still send its profile to a server that has been updated to handle the larger
set of fields.
```fidl
type TemperatureUnit = enum {
CELSIUS = 1;
FAHRENHEIT = 2;
};
type Profile = table {
1: locales vector<string>;
2: calendars vector<string>;
3: time_zones vector<string>;
4: temperature_unit TemperatureUnit;
};
```
### Unions {#unions}
* Record type consisting of an ordinal and an envelope.
* Ordinal indicates member selection, envelope holds contents.
* Declaration can be modified after deployment, while maintaining ABI
compatibility. See the [Compatibility Guide][union-compat] for
source-compatibility considerations.
* Declaration can have the [`resource` modifier](#value-vs-resource).
* Reference may be optional.
* Unions can either be [`strict` or `flexible`](#strict-vs-flexible).
* Unions default to `flexible`.
* `strict` unions must contain one or more members. A union with no members
would have no inhabitants and thus would make little sense in a wire format.
However, memberless `flexible` unions are allowed, as it is still possible to
decode an memberless union (the contained data is always "unknown").
#### Declaration
```fidl
{% includecode gerrit_repo="fuchsia/samples" gerrit_path="src/calculator/fidl/calculator.fidl" region_tag="union" %}
```
#### Use {#unions-use}
Unions are denoted by their declared name (e.g. **Result**) and optionality:
* **`Result`** : required Result
* **`Result:optional`** : optional Result
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="unions-use" %}
```
### Strict vs. flexible {#strict-vs-flexible}
FIDL type declarations can either have **strict** or **flexible** behavior:
* Bits, enums, and unions are flexible unless declared with the `strict`
modifier.
* Structs always have strict behavior.
* Tables always have flexible behavior.
For strict types only, serializing or deserializing a value that contains data
not described in the declaration is a [validation error][lexicon-validate].
In this example:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="strict-vs-flexible" %}
```
By virtue of being flexible, it is simpler for `FlexibleEither` to evolve to
carry a third variant. A client aware of the previous definition of
`FlexibleEither` without the third variant can still receive a union from a
server that has been updated to contain the larger set of variants. If the
union is of the unknown variant, bindings may expose it as unknown data (i.e. as
raw bytes and handles) to the user and allow re-encoding the unknown union (e.g.
to support proxy-like use cases). The methods provided for interacting with
unknown data for flexible types are described in detail in the [bindings
reference][bindings-reference].
More details are discussed in
[RFC-0033: Handling of Unknown Fields and Strictness][rfc-0033].
Note: A type that is both flexible and a [value type](#value-vs-resource) will
not allow deserializing unknown data that contains handles.
### Value vs. resource {#value-vs-resource}
Every FIDL type is either a **value type** or a **resource type**. Resource
types include:
* [handles](#handles)
* [protocol endpoints](#protocols-use)
* [aliases](#aliasing) of resource types
* arrays and vectors of resource types
* structs, tables, and unions marked with the `resource` modifier
* optional (or boxed) references to any of the above types
All other types are value types.
Value types must not contain resource types. For example, this is incorrect:
```fidl
type Foo = struct { // ERROR: must be "resource struct Foo"
h zx.Handle;
};
```
Types can be marked with the `resource` modifier even if they do not contain
handles. You should do this if you intend to add handles to the type in the
future, since adding or removing the `resource` modifier requires
[source-compatibility considerations][resource-compat]. For example:
```fidl
// No handles now, but we will add some in the future.
type Record = resource table {
1: str string;
};
// "Foo" must be a resource because it contains "Record", which is a resource.
type Foo = resource struct {
record Record;
};
```
More details are discussed in [RFC-0057: Default No Handles][rfc-0057].
### Protocols {#protocols}
* Describe methods that can be invoked by sending messages over a channel.
* Methods are identified by their ordinal. The compiler calculates it by:
* Taking the SHA-256 hash of the method's [fully qualified name](#fqn).
* Extracting the first 8 bytes of the hash digest,
* Interpreting those bytes as a little endian integer,
* Setting the upper bit (i.e. last bit) of that value to 0.
* To override the ordinal, methods can have a `@selector` attribute. If the
attribute's argument is a valid FQN, it will be used in place of the FQN
above. Otherwise, it must be a valid identifier, and will be used in place
of the method name when constructing the FQN.
* 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.
* Two-way methods may declare an error type that a server can send
instead of the response. This type must be an `int32`, `uint32`, or an
`enum` thereof.
* When a server of a protocol is about to close its side of the channel, it
may elect to send an **epitaph** message to the client to indicate the
disposition of the connection. The epitaph must be the last message
delivered through the channel. An epitaph message includes a 32-bit int
value of type **zx_status_t**. Negative values are reserved for system
error codes. The value `ZX_OK` (0) indicates an operation was successful.
Application-defined error codes (previously defined as all positive
`zx_status_t` values) are deprecated. For more details about epitaphs, see
rejection of [RFC-0031: Typed Epitaphs][rfc-0031]. For more details about
`zx_status_t` see [RFC-0085: Reducing the zx_status_t space][rfc-0085].
#### Declaration
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="calculator" %}
```
#### Use {#protocols-use}
Protocols are denoted by their name, directionality of the channel, and
optionality:
* **`client_end:Protocol`** : client endpoint of channel communicating over the FIDL protocol
* **`client_end:<Protocol, optional>`** : optional version of the above
* **`server_end:Protocol`** : server endpoint of a channel communicating over the FIDL protocol
* **`server_end:<Protocol, optional>`** : optional version of the above
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="endpoints" %}
```
### Protocol composition {#protocol-composition}
A protocol can include methods from other protocols.
This is called composition: you compose one protocol from other protocols.
Composition is used in the following cases:
1. you have multiple protocols that all share some common behavior(s)
2. you have varying levels of functionality you want to expose to different audiences
#### Common behavior
In the first case, there might be behavior that's shared across multiple protocols.
For example, in a graphics system, several different protocols might all share a
common need to set a background and foreground color.
Rather than have each protocol define their own color setting methods, a common
protocol can be defined:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="composition-base" %}
```
It can then be shared by other protocols:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="composition-inherit" %}
```
In the above, there are three protocols, `SceneryController`, `Drawer`, and `Writer`.
`Drawer` is used to draw graphical objects, like circles and squares at given locations
with given sizes.
It composes the methods **SetBackground()** and **SetForeground()** from
the `SceneryController` protocol because it includes the `SceneryController` protocol
(by way of the `compose` keyword).
The `Writer` protocol, used to write text on the display, includes the `SceneryController`
protocol in the same way.
Now both `Drawer` and `Writer` include **SetBackground()** and **SetForeground()**.
This offers several advantages over having `Drawer` and `Writer` specify their own color
setting methods:
* the way to set background and foreground colors is the same, whether it's used
to draw a circle, square, or put text on the display.
* new methods can be added to `Drawer` and `Writer` without having to change their
definitions, simply by adding them to the `SceneryController` protocol.
The last point is particularly important, because it allows us to add functionality
to existing protocols.
For example, we might introduce an alpha-blending (or "transparency") feature to
our graphics system.
By extending the `SceneryController` protocol to deal with it, perhaps like so:
```fidl
protocol SceneryController {
SetBackground(struct { color Color; });
SetForeground(struct { color Color; });
SetAlphaChannel(struct { a int; });
};
```
we've now extended both `Drawer` and `Writer` to be able to support alpha blending.
#### Multiple compositions
Composition is not a one-to-one relationship &mdash; we can include multiple compositions
into a given protocol, and not all protocols need be composed of the same mix of
included protocols.
For example, we might have the ability to set font characteristics.
Fonts don't make sense for our `Drawer` protocol, but they do make sense for our `Writer`
protocol, and perhaps other protocols.
So, we define our `FontController` protocol:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="composition-multiple-1" %}
```
and then invite `Writer` to include it, by using the `compose` keyword:
```fidl
protocol Writer {
compose SceneryController;
compose FontController;
Text(struct { x int; y int; message string; });
};
```
Here, we've extended the `Writer` protocol with the `FontController` protocol's methods,
without disturbing the `Drawer` protocol (which doesn't need to know anything about fonts).
Protocol composition is similar to [mixin].
More details are discussed in [RFC-0023: Compositional Model][rfc-0023].
#### Layering
At the beginning of this section, we mentioned a second use for composition, namely
exposing various levels of functionality to different audiences.
In this example, we have two protocols that are independently useful, a `Clock` protocol
to get the current time and timezone:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="layering-clock" %}
```
And an `Horologist` protocol that sets the time and timezone:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="layering-horologist" %}
```
We may not necessarily wish to expose the more privileged `Horologist` protocol to just
any client, but we do want to expose it to the system clock component.
So, we create a protocol (`SystemClock`) that composes both:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="layering-systemclock" %}
```
### Unknown interactions {#unknown-interactions}
Protocols can define how they react when they receive a method call or event
which has an ordinal which isn't recognized. Unrecognized ordinals occur
primarily when a client and server were built using different versions of a
protocol which may have more or fewer methods, though it can also occur if
client and server are mistakenly using different protocols on the same channel.
To control the behavior of the protocol when these unknown interactions occur,
methods can be marked as either `strict` or `flexible`, and protocols can be
marked as `closed`, `ajar`, or `open`.
The method strictness modifiers, `strict` and `flexible`, specify how the
sending end would like the receiving end to react to the interaction if it does
not recognize the ordinal. For a one-way or two-way method, the sending end is
the client, and for an event the sending end is the server.
* `strict` means that it should be an error for the receiving end not to know
the interaction. If a `strict` unknown interaction is received, the receiver
should close the channel.
* `flexible` means that the unknown interaction should be handled by the
application. If the protocol allows for that type of unknown interaction,
the ordinal is passed to an unknown interaction handler which can then
decide how to react to it. What types of unknown interactions a protocol
allows is determined by the protocol modifier. `flexible` is the default
value if no strictness is specified.
The protocol openness modifiers, `closed`, `ajar` and `open` control how the
receiving end reacts to `flexible` interactions if it does not recognize the
ordinal. For a one-way or two-way method, the receiving end is the server, and
for an event, the receiving end is the client.
* `closed` means the protocol does not accept any unknown interactions. If any
unknown interaction is received, the bindings report an error and end
communication, regardless of whether the interaction is `strict` or
`flexible`.
* All methods and events must be declared as `strict`.
* `ajar` means that the protocol allows unknown `flexible` one-way methods and
events. Any unknown two-way methods and `strict` one-way methods or events
still cause an error and result in the bindings closing the channel.
* One-way methods and events may be declared as either `strict` or
`flexible`.
* Two-way methods must be declared as `strict`.
* `open` means that the protocol allows any unknown `flexible` interactions.
Any unknown `strict` interactions still cause an error and result in the
bindings closing the channel. Open is the default value if no openness is
specified.
* All methods and events may be declared as either `strict` or `flexible`.
Here is a summary of which strictness modifiers are allowed for different kinds
of methods in each protocol type. The default value of openness, `open`, marked
in _italics_. The default value of strictness, `flexible`, is marked in
**bold**.
| | strict M(); | **flexible M();** | strict -> M(); | **flexible -> M();** | strict M() -> (); | **flexible M() -> ();** |
|----------|-------------|----------------------|----------------|----------------------|-------------------|-------------------------|
| _open P_ | _compiles_ | **_compiles_** | _compiles_ | **_compiles_** | _compiles_ | **_compiles_** |
| ajar P | compiles | **compiles** | compiles | **compiles** | compiles | **fails to compile** |
| closed P | compiles | **fails to compile** | compiles | **fails to compile** | compiles | **fails to compile** |
Example usage of the modifiers on a protocol.
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="unknown-interactions" %}
```
Keep in mind that unknown interaction handling applies only when the receivng
end doesn't recognize the ordinal and doesn't know what the interaction is.
This means that the receiving end does not know whether the interaction is
supposed to be strict or flexible. To allow the receiver to know how to handle
an unknown interaction, the sender includes a bit in the message header which
tells the receiver whether to treat the interaction as strict or flexible.
Therefore, the strictness used in an interaction is based on what strictness the
sender has for the method it tried to call, but the protocol's openness for that
interaction depends on what openness the receiver has.
Here's how a method or event with each strictness is handled by a protocol with
each openness when the receiving side doesn't recognize the method.
| | strict M(); | flexible M(); | strict -> M(); | flexible -> M(); | strict M() -> (); | flexible M() -> (); |
|----------|-------------|---------------|----------------|------------------|-------------------|---------------------|
| open P | auto-closed | handleable | auto-closed | handleable | auto-closed | handleable |
| ajar P | auto-closed | handleable | auto-closed | handleable | auto-closed | auto-closed |
| closed P | auto-closed | auto-closed | auto-closed | auto-closed | auto-closed | auto-closed |
#### Interaction with composition
`flexible` methods and events cannot be declared in `closed` protocols and
`flexible` two-way methods cannot be declared in `ajar` protocols. To ensure
these rules are enforced across protocol composition, a protocol may only
compose other protocols that are at least as closed as it is:
* `open`: Can compose any protocol.
* `ajar`: Can compose `ajar` and `closed` protocols.
* `closed`: Can only compose other `closed` protocols.
### Aliasing {#aliasing}
Type aliasing is supported. For example:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="aliasing" %}
```
In the above, the identifier `StoryID` is an alias for the declaration of a
`string` with a maximum size of `MAX_SIZE`. The identifier `Chapters` is an
alias for a vector declaration of five `StoryId` elements.
The identifiers `StoryID` and `Chapters` can be used wherever their aliased
definitions can be used.
Consider:
```fidl
{% includecode gerrit_repo="fuchsia/fuchsia" gerrit_path="examples/fidl/fuchsia.examples.docs/language_reference.test.fidl" region_tag="aliasing-usage" %}
```
Here, the `Message` struct contains a string of `MAX_SIZE` bytes called `baseline`,
and a vector of up to `5` strings of `MAX_SIZE` called `chapters`.
<<../../../development/languages/fidl/widgets/_alias.md>>
### Builtins
FIDL provides the following builtins:
* Primitive types: `bool`, `int8`, `int16`, `int32`, `int64`, `uint8`, `uint16`,
`uint32`, `uint64`, `float32`, `float64`.
* Other types: `string`, `client_end`, `server_end`.
* Type templates: `array`, `vector`, `box`.
* Aliases: `byte`.
* Constraints: `optional`, `MAX`.
All builtins below to the `fidl` library. This library is always available and
does not need to be imported with `using`. For example, if you declare a struct
named `string`, you can refer to the original string type as `fidl.string`.
#### Library `zx` {#zx-library}
Library `zx` is not built in, but it is treated specially by the compiler. It is
defined in [//zircon/vdso/zx](/zircon/vdso/zx). Libraries import it with
`using zx` and most commonly use the `zx.Handle` type.
### Inline layouts {#inline-layouts}
Layouts can also be specified inline, rather than in a `type` introduction
declaration. This is useful when a specific layout is only used once. For
example, the following FIDL:
```fidl
type Options = table {
1: reticulate_splines bool;
};
protocol Launcher {
GenerateTerrain(struct {
options Options;
});
};
```
can be rewritten using an inline layout:
```fidl
protocol Launcher {
GenerateTerrain(struct {
options table {
1: reticulate_splines bool;
};
});
};
```
When an inline layout is used, FIDL will reserve a name for it that is
guaranteed to be unique, based on the [naming context][naming-context] that the
layout is used in. This results in the following reserved names:
* For inline layouts used as the type of an outer layout member, the reserved
name is simply the name of the corresponding member.
* In the example above, the name `Options` is reserved for the inline
`table`.
* For top level request/response types, FIDL concatenates the protocol name,
the method name, and then either `"Request"` or `"Response"` depending on
where the type is used.
* In the example above, the name `LauncherGenerateTerrainRequest` is
reserved for the struct used as the request of the `GenerateTerrain`
method.
* Note that the `"Request"` suffix denotes that the type is used to initiate
communication; for this reason, event types will have the `"Request"`
suffix reserved instead of the `"Response"` suffix.
The name that is actually used in the generated code depends on the binding, and
is described in the individual [bindings references][bindings-reference].
For inline layouts used as the type of a layout member, there are two ways to
obtain a different reserved name:
* Rename the layout member.
* Override the reserved name using the [`@generated_name`][generated-name-attr]
attribute.
[mixin]: https://en.wikipedia.org/wiki/Mixin
[rfc-0023]: /docs/contribute/governance/rfcs/0023_compositional_model_protocols.md
[rfc-0031]: /docs/contribute/governance/rfcs/0031_typed_epitaphs.md
[rfc-0033]: /docs/contribute/governance/rfcs/0033_handling_unknown_fields_strictness.md
[rfc-0057]: /docs/contribute/governance/rfcs/0057_default_no_handles.md
[rfc-0085]: /docs/contribute/governance/rfcs/0085_reducing_zx_status_t_space.md
[fidl-overview]: /docs/concepts/fidl/overview.md
[fidl-grammar]: /docs/reference/fidl/language/grammar.md
[doc-attribute]: /docs/reference/fidl/language/attributes.md#Doc
[naming-style]: /docs/development/languages/fidl/guides/style.md#Names
[compat]: /docs/development/languages/fidl/guides/compatibility/README.md
[union-compat]: /docs/development/languages/fidl/guides/compatibility/README.md#union
[resource-compat]: /docs/development/languages/fidl/guides/compatibility/README.md#modifiers
[bindings-reference]: /docs/reference/fidl/bindings/overview.md
[lexicon-validate]: /docs/reference/fidl/language/lexicon.md#validate
[wire-format]: /docs/reference/fidl/language/wire-format/README.md
[naming-context]: /docs/contribute/governance/rfcs/0050_syntax_revamp.md#layout-naming-contexts
[generated-name-attr]: /docs/reference/fidl/language/attributes.md#generated-name
[Life of a handle]: /docs/concepts/fidl/life-of-a-handle.md
[library-overview]: /docs/development/languages/fidl/guides/style.md#library-overview