ESOTERIC STANDARD COMMITTEE Esoteric Syntax Notation ESOSC-2018-D20 Introduction ------------ This standard describes a language to specify data structures and a serialization and deserialization profile. Data Types ---------- The following primitive data types exist: - INTEGER - BOOL - UINTEGER - BINARY - STRING - FLOAT - LIST Further there is STRUCT which is a composite data type. Size Options ============ Data types may have size options that are denoted in brackets. - TYPE[n] indicates that the type is of at least size n. - TYPE[n,m] indicates that the type is of at least size n but at most of size m. - TYPE[*,m] indicates that the type is at most of size m. - TYPE[n,*] indicates that the type is at least of size n. However, not all sizes are valid for each type. There's no INTEGER of size 0 for example and no INTEGER of size 3. INTEGER ======= INTEGER is a data type for signed integer values. They exist in the different sizes of 1, 2, 4, 8 bytes. INTEGER may have an exact required size or a minimum and maximum size. BOOL ==== BOOL is a data type for truth values. It is either TRUE or FALSE. UINTEGER ======== UINTEGER is a data type for unsigned integer values. They exist in the different sizes of 1, 2, 4, 8 bytes. UINTEGER may have an exact required size or a minimum and maximum size. BINARY ====== BINARY is a data type for raw binary data as bytes. STRING ====== STRING is a data type for text strings. They must be encoded using utf-8. STRUCT ====== A STRUCT is a composite data type consisting of 'fields'. Each field has an identifier and a data type. [EX-1] someStruct := STRUCT sid:unspecified-0 { 0x00, mandatory: INTEGER[4] 0x01, mandatory: INTEGER[4] 0x02, optional: STRUCT sid:unspecified-1 { 0x00, mandatory: FLOAT[4] 0x01, optional: FLOAT[8] } } [/EX-1] A STRUCT has a structure identifier (SID). Structure identifier identify commonly used structures. SIDs are assigned by the ESOSC. They are useful for fields that may be either a struct of one type or a struct of another type using a choice operator. [EX-2] someStruct := STRUCT sid:unspecified-0 { 0x00, mandatory-choice: STRUCT sid:unspecified-1 , STRUCT sid:unspecified-2 } someStruct1 := STRUCT sid:unspecified-1 { 0x00, mandatory: INTEGER[1] 0x01, mandatory: INTEGER[1] } someStruct2 := STRUCT sid:unspecified-2 { 0x00, mandatory: STRING[4] 0x01, mandatory: STRING[4] } [/EX-2] FLOAT ========= LIST ======== LIST is a data type that contains an amount of values of other data types. LIST may have an exact required size or a maximum and minimum size (in element) denoted in brackets. LIST(INTEGER[4])[2] specifies a list that must contain exactly two integers. LIST(INTEGER[2,4])[2,3] specifies a list that must contain at least two integers but at most 4 integers where each integer may either be of at least size 2 or at most size 4. The ESN language ---------------- (De-)serialization of ESN structures ------------------------------------ Each value has a one byte prefix indicating the data type. These prefixes are: - 0000SSSS for INTEGER - 00010000 for BOOL - 0010SSSS for UINTEGER - 00110000 for BINARY - 01000000 for STRING - 0101SSSS for FLOAT - 01100000 for LIST The lower nibble represent additional flags. The SSS is a three bit value indicating the size in bytes of the types and indicates how many bytes follow the prefix. [EX-3] 00000010 iiiiiiii iiiiiiii - A two byte INTEGER 00000011 iiiiiiii iiiiiiii iiiiiiiii - Invalid. 3 is not a valid INTEGER size. [/EX-3] When deserializing an implementation should verify that the size matches the specification of the data structure. [EX-4] Specification: value := INTEGER[4,8] Data: 00000010 iiiiiiii iiiiiiii - Invalid. 'value' must be at least of size 4.