Google is committed to advancing racial equity for Black communities. See how.

Dart bindings

Libraries

Given the library declaration:

library games.tictactoe;

The bindings code for this library is generated into a fidl_games_tictactoe_async dart library. The fidl_ prefix and _async suffix are hardcoded by the FIDL toolchain.

This code can then be imported using:

import 'package:fidl_games_tictactoe/fidl_async.dart' as tictactoe;

Constants

All constants are generated as a const. For example, the following constants:

const uint8 BOARD_SIZE = 9;
const string NAME = "Tic-Tac-Toe";

Are generated as:

const int BOARD_SIZE = 9;
const String NAME = "Tic-Tac-Toe";

The correspondence between FIDL primitive types and Dart types is outlined in built-in types.

Fields

This section describes how the FIDL toolchain converts FIDL types to native types in Dart. These types can appear as members in an aggregate type, as parameters to a protocol method, or as the type contained in an event or method response Future.

Nullable types do not have different generated types than their non-nullable counterparts in Dart.

Built-in types

The FIDL types are converted to Dart types based on the following table:

FIDL Type Dart Type
bool bool
int8, int16, int32, int64, uint8, uint16, uint32, uint64 int
float32, float64 double
array<int8>:N, vector<int8>:N Int8List
array<int16>:N, vector<int16>:N Int16List
array<int32>:N, vector<int32>:N Int32List
array<int64>:N, vector<int64>:N Int64List
array<uint8>:N, vector<uint8>:N Uint8List
array<uint16>:N, vector<uint16>:N Uint16List
array<uint32>:N, vector<uint32>:N Uint32List
array<uint64>:N, vector<uint64>:N Uint64List
array<float32>:N, vector<float32>:N Float32List
array<float64>:N, vector<float64>:N Float64List
array<T>:N, vector<T>:N List<T>
string String
request<P> fidl.InterfaceRequest<P>
P fidl.InterfaceHandle<P>
handle<channel> zircon.Channel
handle<eventpair> zircon.EventPair
handle<socket> zircon.Socket
handle<vmo> zircon.Vmo
handle<S>, handle zircon.Handle

Response and event parameters

Method response and event types (see Protocols) are represented using Future<T>, where T is a type containing all of the response/event parameters. This section describes how the FIDL toolchain generates this inner type T.

  • Empty responses and events use void.
  • Responses and events with a single parameter T just use T as the response or event type.
  • Responses and events with multiple parameters use a generated wrapper class which follows the naming scheme [Protocol]$[Method]$Response. For example, an event OnOpponentMove for protocol TicTacToe that has multiple parameters would use generated class TicTacToe$OnOpponentMove$Response. This class provides a single method: the constructor, which has positional arguments corresponding to the response or event parameters.

Note that methods that do not have a response will have a response type of Future<void>, which is the same type used by methods with an empty response. In the former case, the Future can be expected to resolve immediately after sending the request, whereas in the latter case, the Future is only resolved after receiving the empty response from the server.

Type definitions

Bits

Given the bits definition:

bits FileMode : uint16 {
    READ = 0b001;
    WRITE = 0b010;
    EXECUTE = 0b100;
};

The FIDL toolchain generates a FileMode class with static const variables for each bits member, as well as for a FileMode with no flags set:

  • static const FileMode read
  • static const FileMode write
  • static const FileMode execute
  • static const FileMode $none

FileMode provides the following methods:

  • int get $value: Getter for the underlying int value.
  • String toString(): Returns a readable representation of the FileMode.
  • FileMode operator |(FileMode other): Bitwise or operator.
  • FileMode operator &(FileMode other): Bitwise and operator.
  • bool operator(dynamic other): Equality operator.

Enums

Given the enum definition:

enum Color {
    RED = 1;
    GREEN = 2;
    BLUE = 3;
};

The FIDL toolchain generates a Color class with static const variables for each enum member:

  • static const Color red
  • static const Color green
  • static const Color blue

As well as the following variables:

  • static const Map<String, Color> $valuesMap: A mapping ofthe string representation of the member ('red', 'green', or 'blue') to its corresponding enum value (Color.red, Color.green, or Color.blue)
  • static const List<Color> $values: A list of all of the Colors.

Color provides the following methods:

  • factory Color(int v): Factory constructor that returns the corresponding Color static const variable (red, green, or blue) if the input matches one of the discriminants, or null otherwise.
  • static Color $valueOf(String name): Look up a string name in the $valuesMap.
  • String toString(): Returns a readable representation of the Color.

Structs

Given the struct declaration:

struct Color {
    uint32 id;
    string name = "red";
};

The FIDL toolchain generates a Color class with the following methods:

  • const Color({@required id, name}): The constructor for Color takes named arguments corresponding to the struct's fields. Fields that are not nullable and do not have a default value specified are marked as @required.
  • Color.clone(Color, {int id, String name}): Clone constructor that will clone an existing Color, possibly overriding specific field values based on the provided named arguments.
  • List<Object> get $fields: Returns a list of fields in declaration order.
  • String toString(): Returns a readable string of the Color
  • bool operator==(dynamic other): Equality operator that performs a deep comparison when compared to another instance of a Color.

Unions

Given the union definition:

union JsonValue {
    1: reserved;
    2: int32 int_value;
    3: string string_value;
};

FIDL generates an enum representing the tags of the union:

enum JsonValueTag {
  intValue,
  stringValue,
}

As well as a JsonValue class with the following methods:

  • const JsonValue.withIntValue(int) and const JsonValue.withStringValue(String): Constructors for each variant.
  • JsonValueTag get $tag: Getter for the tag corresponding to this the variant of this union.
  • int get intValue and String get stringValue: Getter for the underlying value. If the instance's variant does not match the getter method, null is returned.
  • String toString(): Returns a readable string of the JsonValue.
  • int get $ordinal: Setter for the underlying ordinal value.
  • Object get $data: Setter for the underlying union data.
  • bool operator ==(dynamic other): Equality operator that performs deep comparison when compared to another JsonValue of the same variant.

Flexible unions and unknown variants

Flexible unions (that is, unions that are prefixed with the flexible keyword in their FIDL definition) have an extra variant in the generated tag class:

enum JsonValueTag {
  $unknown,
  intValue,
  stringValue,
}

When a FIDL message containing a union with an unknown variant is decoded into JsonValue, JsonValue.$tag returns JsonValueTag.$unknown, and JsonValue.$ordinal returns the unknown ordinal.

Encoding a union with an unknown variant writes the unknown data and the original ordinal back onto the wire.

Non-flexible (i.e. strict) unions fail when decoding a data containing an unknown variant.

Tables

Given the table definition:

table User {
    1: reserved;
    2: uint8 age;
    3: string name;
};

The FIDL toolchain generates a User class that defines the following methods:

  • const User({age, name}): Constructor for User.
  • Map<int, dynamic> get $fields: Returns a map of ordinals to field values.
  • bool operator ==(dynamic other): Equality operator that performs deep comparison when compared to another User.

Protocols

Given the protocol:

protocol TicTacToe {
    StartGame(bool start_first);
    MakeMove(uint8 row, uint8 col) -> (bool success, GameState? new_state);
    -> OnOpponentMove(GameState new_state);
};

FIDL generates an abstract TicTacToe class, which defines the interface of the service used by clients to proxy calls to the server, and for the server for implementing the protocol.

TicTacToe contains a static const String $serviceName, which is defined depending on the presence of the [Transitional] attribute.

TicTacToe has the following abstract methods, representing the protocol methods:

  • async.Future<void> startGame(bool start_first): Abstract method for a fire and forget protocol method. It takes as arguments the request parameters and returns a future of void.
  • async.Future<TicTacToe$MakeMove$Response> makeMove(int row, int col): Abstract method for a two way protocol method. It takes as arguments the request parameters and returns a future of the response type.
  • async.Stream<GameState> get onOpponentMove: Getter for a Stream of onOpponentMove events.

Client

The FIDL toolchain generates a TicTacToeProxy class that extends fidl.AsyncProxy<TicTacToe>, and provides an implementation for the abstract TicTacToe class that encodes and sends the request to the server end of the channel.

Example client code could thus look like the following:

final tictactoe = fidl_tictactoe.TicTacToeProxy();
// ...bind the proxy, omitted from this example
tictactoe.startGame(true);
final state = await tictactoe.makeMove(0, 0);

Examples on how to set up and bind a proxy class to a channel are covered in the Dart tutorial.

Server

Implementing a server for a FIDL protocol involves providing a concrete implementation of TicTacToe abstract class.

Examples on how to set up and bind a server implementation are covered in the Dart tutorial.

Events

Client

The TicTacToeProxy class automatically implements the onOpponentMove getter. Clients obtain an async.Stream of onOpponentMove events sent from the server using this getter.

Server

Servers send events by implementing the onOpponentMove getter on the abstract TicTacToe class. A TicTacToeBinding (see tutorial) that is bound to an instance of TicTacToe that has implemented the onOpponentMove getter will listen for events on the returned async.Stream, forwarding them to the client.

Results

Given the method with an error type:

protocol TicTacToe {
    MakeMove(uint8 row, uint8 col) -> (GameState new_state) error MoveError;
};

The method signature for MakeMove on the generated abstract TicTacToe class is:

async.Future<GameState> makeMove(int row, int col)

The encapsulated Future corresponds to the generated response type for the success case, and the error case is represented by having the server implementation or the proxy class throw a fidl.MethodException.

Using this feature, an example implementation of MakeMove on the server side could look like:

@override
async.Future<GameState> makeMove(int row, int col) {
  if (row > 9 || col > 9) {
    return async.Future.error(fidl.MethodException(MoveError.OutOfBounds));
  }
  return async.Future.value(doSomething(row, col));
}

The TicTacToeBinding class will catch fidl.MethodExceptions and encode it as an error.

An example of using this on the client side would be:

myproxy.makeMove(1, 2).then((gameState) { ... })
                      .catchError((moveError) { ... });

Protocol composition

FIDL does not have a concept of inheritance, and generates full code as described above for all composed protocols. In other words, the code generated for:

protocol A {
    Foo();
};

protocol B {
    compose A;
    Bar();
};

Provides the same API as the code generated for:

protocol A {
    Foo();
};

protocol B {
    Foo();
    Bar();
};

The generated code is identical except for the method ordinals.

Protocol and method attributes

Transitional

For protocol methods annotated with the [Transitional] attribute, the FIDL toolchain generates a default implementation on the abstract class so that server implementations will continue to compile without having to override the new method.

Discoverable

The generated class for a protocol annotated with the [Discoverable] attribute has a non-null $serviceName field.

Test scaffolding

The FIDL toolchain generates a fidl_test.dart file that contains convenience code for testing FIDL server implementations. This file contains a class for each protocol that provides stub implementations for each of the class’s methods, making it possible to implement only the methods that are used during testing.

Given the example protocol above, The FIDL toolchain generates a TicTacToe$TestBase class that extends the TicTacToe abstract class. All methods are implemented by returning async.Future.error(UnimplementedError()), and all events are implemented by returning a Stream with a single UnimplementedError event.