Link Search Menu Expand Document

APX IDL v1.2

This is the specification for the APX Interface Definition Language (IDL) v1.2.

Table of contents

  1. Definition files
  2. APX Header
  3. Statements and specifiers
  4. Node Declarations
  5. Type Declarations
  6. Data Signatures
  7. Type Attributes
  8. Port Declarations
  9. Port Attributes
  10. Full Language Specification

Definition files

APX IDL is used when writing definition files that use the .apx file extension. Preferably these files should be generated by a toolchain but they can on occasion be written by hand.

Each file shall be used to describe one APX node. It’s not allowed (in this version of IDL) to place multiple node declarations in the same file.

Line endings

The only acceptable line ending (or EOL) is the UNIX line ending (\n). If you are a Windows developer you must remember to convert your APX definition file to UNIX line ending before use with any of the implementations.

Structure of an APX Definition File

  1. APX Header
  2. Node Declaration
  3. [Type Declaration(s)]
  4. Port Declaration(s)

Example:

APX/1.2
N"Example"
T"VehicleSpeed_T"S
T"EngineSpeed_T"S
P"VehicleSpeed"T[0]:=65535
P"EngineSpeed"T[1]:=65535

APX Header

The first line of the definition file must contain an APX header. This is inspired by the HTTP header and contains the letters APX/ followed by the IDL version.

Example:

APX/1.2

Statements and specifiers

Following the APX header line are one or more APX statement lines. The first letter of each line sets what kind of statement it is.

There can be at most one statement per line as there is no statement separator in APX IDL.

Node Declarations

A node declaration begins a new APX node. All lines following it belongs to that node. Each node has a name (string literal), it must be unique within the same APX client. There can only be a single node declaration for each definition file.

A Node declaration does not have an attribute section, only a name.

Example:

N"MyNode"

Type Declarations

A type declaration statement creates a new type that can be referenced later by one or more port declarations.

‘T’ Name Data-Signature

Example:

# Type "VehicleSpeed_T" with type uint16
T"VehicleSpeed_T"S

You can also add an optional type attribute section separated by a : character.

‘T’ Name Data-Signature ’:’ Type-Attribute

Example:

# Type "OffOn_T" with type uint8 and range 0..3
T"VehicleSpeed_T"C(0,3):VT("OffOn_Off", "OffOn_On", "OffOn_Error", "OffOn_NotAvailable")

Data Signatures

Primitive Type Codes

APX uses single letter type codes. In general (but not always) a lower-case letter means signed while an upper-case letter means unsigned.

Type Code Platform Type Bits Lower Limit Upper Limit
c int8 8 -128 127
s int16 16 -32768 32767
l int32 32 -2147483648 2147483647
u int64 64 -(2^63) (2^63)-1
C uint8 8 0 255
S uint16 16 0 65535
L uint32 32 0 4294967295
U uint64 64 0 (2^64)-1
a unsigned char 8 0 255

Array Types

Any primitive type code can be followed by [n] where n is the number of array elements.

Examples:

C[3]     # type: uint8, array-length: 3, memory-size: 3
S[4]     # type: uint16, array-length: 4, memory-size: 8 bytes

Strings

Declaring an array using the a type code turns the type into a string. The array length in that case declares how many bytes the string can contain (at the most).

APX allows writing of strings whose length are shorter to or equal to the maximum number of array elements (bytes). In that case, APX automatically sets the remaining bytes in the string to zero or null. This is not the case for other array types. reading and writing these ports must contain data that matches the number of array elements in the declaration.

Examples:

a[10]    # type string, array-length: 10, memory-size: 10 bytes
a[40]    # type string, array-length: 40, memory-size: 40 bytes

Data Limits

All primitive type codes can have an optional lower/upper limit. This is done by adding (Lower, Upper) right after the type code.

  • Lower: Lower data limit (decimal integer)
  • Upper: Upper data limit (decimal integer)

If no data limit is defined it will implicitly derive the data limit from the underlying primitve type.

When a data limit is combined with an array declaration the limit declaration is always placed before the array declaration

Examples:

C(0,1)       #type:uint8, lower-limit: 0, upper-limit: 1
C(0,3)       #type:uint8, lower-limit: 0, upper-limit: 3
S(0,10000)   #type:uint16, lower-limit: 0, upper-limit: 10000
C            #type: uint8, lower-limit: 0 (implicit), upper-limit: 255 (implicit)
S            #type: uint8, lower-limit: 0 (implicit), upper-limit: 65535 (implicit)
C(0,3)[10]   #type: uint8, array-length: 10, lower-limit (for each elem): 0 upper-limit (for each elem): 3

Record Types

Record types (sometimes known as struct types) can be declared in APX by wrapping the data signature in braces {}.

After the opening brace { Any number of record elements can be added until the closing brace } is seen.

Each record elements consist of type parts in the following order.

Record elements are entered one after the other (name, data signature, name data signature, etc.). No whitespace or separators (such as commas are allowed). The order of record elements data is preserved during serialization/deserialization.

Examples:

# Record with 2 elements. "UserId" has type uint32 while "UserName" is a string of max 64 bytes.
{"UserId"L"UserName"a[64]}
#Record with 3 elements named "Red", "Green" and "Blue". Each element is of type uint8.
{"Red"C"Green"C"Blue"C}

For this version of the IDL, any APX implementation do not need to support records to be defined within records (nested structures). APX IDL 1.3 however has that conformance requirement.

Type References

Data signatures can reference a type definition by using capital letter T followed by the index of the data type enclosed in brackets [].

Example:

T"VehicleSpeed_T"S          # This type has index 0
T"EngineSpeed_T"S           # This type has index 1
P"VehicleSpeed"T[0]:=65535  # References VehicleSpeed_T
P"EngineSpeed"T[1]:=65535   # Reference EngineSpeed_T

This version of the IDL does not support type reference by name (see APX IDL v1.3).

Type Attributes

In this version of the IDL there is only a single type attribute, the value table.

Value Table

A value table maps enumeration names onto a data type. You declare it using the VT() syntax where you place a list string literals inside the parenthesis. Each string literal shall be separated by a comma.

Example:

VT("OffOn_Off", "OffOn_On", "OffOn_Error", "OffOn_NotAvailable")

This version of the IDL does not have any fancy options such as manually selecting what string literal is assigned to what value etc.

Port Declarations

There are two types of ports in APX, Require-ports and Provide-ports. The only difference between them is wether the data is coming into or going out from the APX node.

Require-port Declaration

A Require port declaration starts with capital letter R followed by its name and data signature.

‘R’ Name Data-Signature

Example:

# Require-port "VehicleSpeed" with data type uint16
R"VehicleSpeed"S
# Require-Port "EngineSpeed" with type reference 1
R"EngineSpeed"T[1]

The port definition can also have an optional port attribute section separated by the : character.

‘R’ Name Data-Signature ’:’ Port-Attributes

Example:

# Require-port "VehicleSpeed" with data type uint16 and init-value 65535
R"VehicleSpeed"S:=65535
# Require-Port "EngineSpeed" with type reference 1 and init-value 65535
R"EngineSpeed"T[1]:=65535

Provide-port Declaration

A Provide-port declaration starts with capital letter P followed by its name and data signature.

‘P’ Name Data-Signature

Example:

# Provide-Port "VehicleSpeed" with data type uint16
P"VehicleSpeed"S
# Provide-Port "EngineSpeed" with type reference 1
P"EngineSpeed"T[1]

The port definition can also have an optional port attribute section separated by the : character.

‘P’ Name Data-Signature ’:’ Port-Attributes

Example:

# Provide-port "VehicleSpeed" with data type uint16 and init-value 65535
P"VehicleSpeed"S:=65535
# Provide-Port "EngineSpeed" with type reference 1 and init-value 65535
P"EngineSpeed"T[1]:=65535

Port Attributes

Port attributes is a list of characters that is placed after the : in a port declaration. Some port attributes are a single character while other can be more than one character.

  • Each attribute must be separated by a comma.
  • The order of the attributes does not matter, they all get applied to your port declaration.

Init-Value

The init-value attribute sets the initial value of the port data. If no init value exists, the port data will be initialized to zero. This attribute can be 2 or more characters depending on the complexity of the port data signature.

The first character of this attribute must be the equal-sign =, this identfies the character(s) to come after it to be part of the init-value (until either next comma or end-of-line is encountered).

APX accepts four different forms of initializers:

  • decimal
  • hexadecimal
  • string
  • record

Decimal and Hexadecimal Initializers

The most common form of initializer is a decimal integer. APX also accepts hexadecimal initializers when prefixed with 0x.

Examples:

=7               #Decimal init-value
=255             #Decimal init-value
=0xff            #Hexadecimal init-value
=0xffff          #Hexadecimal init-value

String Initializer

When the data signature is of string type (arrray of typecode a) a string initializer is expected. Not all implementations of APX IDL v1.2 supports unicode characters as part of the initializer so it is best not to use them until all implementations supports APX IDL v1.3.

Example:

=""               #Empty string initializer.

Record Initializer

Record initializer works similarly to C struct initializers. The initializer must be a non-empty, brace-enclosed, comma-separated list of initializers for each member in the data signature.

Example:

={255, 255, 255} #Record initializer for data signature containing 3 members.

Full Language Specification

Document
    ApxHeader '\n' Statements

ApxHeader
    'APX/1.2'

Statements
    Statement '\n'
    Statement '\n' Statement

Statement
   NodeDeclaration
   TypeDeclaration
   RequirePortDeclaration
   ProvidePortDeclaration

NodeDeclaration
    'N' Name

TypeDeclaration
    'T' Name TypeSignature
    'T' Name TypeSignature ':' TypeAttributes

RequirePortDeclaration
    'R' Name TypeSignature
    'R' Name TypeSignature ':' PortAttributes

ProvidePortDeclaration
    'P' Name TypeSignature
    'P' Name TypeSignature ':' PortAttributes

Name
    '"' NameChars '"'

Names
    Name
    Name ',' Names

NameChars
    NameChar
    NameChar NameChars

NameChar
    'a' . 'z'
    'A' . 'Z'
    '0' . '9'
    '_'
    '-'

TypeSignature
    PrimitiveType
    PrimitiveType '[' OneNine Digits ']'
    'T[' Digits ']'
    '{' RecordElements '}'

PrimitiveType
    c
    s
    l
    u
    C
    S
    L
    U

RecordElements
    Name TypeSignature
    Name TypeSignature ',' RecordElements

TypeAttributes
    TypeAttribute
    TypeAttribute ',' TypeAttributes

TypeAttribute
    VT(Names)

PortAttributes
    PortAttribute
    PortAttributes ',' PortAttributes

PortAttribute
    '=' Integer
    '=' StringLiteral

Integer
    Digit
    OneNine Digits
    '-' Digit
    '-' OneNine Digits
    '0x' HexDigits

Digits
    Digit
    Digit Digits

Digit
    '0'
    OneNine

OneNine
    '1' . '9'
HexDigits
    HexDigit
    HexDigit HexDigits

HexDigit
    Digit
    'a' . 'f'
    'A' . 'F'

StringLiteral
    '"' '"'
    '"' Characters '"'

Characters
    character
    character characters

character
    '0020' . '007F' - '"'