liberty/libertyxdr.adoc

3.2 KiB
Raw Permalink Blame History

libertyxdr(7)

Name

LibertyXDR - an XDR-derived IDL and data serialization format

Description

LibertyXDR is an interface description language, as well as a data serialization format. It is largely derived from XDR, though notably simplified.

Conventions

User-defined types should be named in CamelCase, field names in snake_case, and constants in SCREAMING_SNAKE_CASE. Code generators will convert these to whatever is appropriate in their target language.

Primitive data types

Like in XDR, all data is serialized in the network byte order, i.e., big-endian.

  • void: 0 bytes

    This is a dummy type that cannot be assigned a field name.

  • bool: 1 byte

    This is a boolean value: 0 means false, any other value means true.

  • u8, u16, u32, u64: 1, 2, 4, and 8 bytes respectively

    These are unsigned integers.

  • i8, i16, i32, i64: 1, 2, 4, and 8 bytes respectively

    These are signed integers in twos complement.

  • string: implicitly prefixed by its length as a u32, then immediately followed by its contents, with no trailing NUL byte

    This is a valid UTF-8 string without a byte order mark. Note that strings are always unbounded, unlike in XDR.

Constants

At the top level of a document, outside other definitions, you can define typeless integer constants:

const VERSION = 1;

The value can be either a name of another previously defined constant, or an immediate decimal value, which may not contain leading zeros.

Enumerations

An enum is an i8 with uniquely named values, in their own namespace.

Values can be either specified explicitly, in the same way as with a constant, or they can be left implicit, in which case names assume a value that is one larger than their predecessor. Zero is reserved for internal use, thus enumerations implicitly begin with a value of one. For example, these form a sequence from one to three:

enum Vehicle { CAR, LORRY = 2, PLANE, };

Structures

A struct is a sequence of fields, specified by their type, and their chosen name. You can add a <> suffix to change a field to an array, in which case it is implicitly preceded by a u32 specifying its length in terms of its elements.

Unlike in XDR, there is no padding between subsequent fields, and type definitions can be arbitrarily syntactically nested, as in C.

struct StockReport {
  u8 version;       // Version of this report.
  struct Item {
    Vehicle kind;   // The vehicle in question.
    i32 count;      // How many vehicle of that kind there are.
  } items<>;        // Reported items.
};

Unions

A union is a kind of structure whose fields depend on the value of its first and always-present field, which must be a tag enum:

union VehicleDetails switch (Vehicle kind) {
case CAR:   void;
case LORRY: i8 axles;
case PLANE: i8 engines;
};

All possible enumeration values must be named, and there is no case fall-through.

Framing

Unless this role is already filled by, e.g., WebSocket, LibertyXDR structures should be prefixed by their byte length in the u32 format, once serialized.

See also

XDR: External Data Representation Standard, RFC 4506