Binary SATN Format (BSATN)
The Spacetime Algebraic Type Notation binary (BSATN) format defines
how Spacetime AlgebraicValues and friends are encoded as byte strings.
Algebraic values and product values are BSATN-encoded for e.g., module-host communication and for storing row data in the database.
Notes on notation
In this reference, we give a formal definition of the format. To do this, we use inductive definitions, and define the following notation:
bsatn(x)denotes a function converting some valuexto a list of bytes.a: Bmeans thatais of typeB.Foo(x)denotes extractingxout of some variant or typeFoo.a ++ bdenotes concatenating two byte listsaandb.bsatn(A) = bsatn(B) | ... | bsatn(Z)whereBtoZare variants ofAmeans thatbsatn(A)is defined as e.g.,bsatn(B),bsatn(C), ..,bsatn(Z)depending on what variant ofAit was.[]denotes the empty list of bytes.
Values
At a glance
| Type | Description |
|---|---|
AlgebraicValue | A value of any type. |
SumValue | A value of a sum type, i.e. an enum or tagged union. |
ProductValue | A value of a product type, i.e. a struct or tuple. |
AlgebraicValue
The BSATN encoding of an AlgebraicValue defers to the encoding of each variant:
bsatn(AlgebraicValue)
= bsatn(SumValue)
| bsatn(ProductValue)
| bsatn(ArrayValue)
| bsatn(String)
| bsatn(Bool)
| bsatn(U8) | bsatn(U16) | bsatn(U32) | bsatn(U64) | bsatn(U128) | bsatn(U256)
| bsatn(I8) | bsatn(I16) | bsatn(I32) | bsatn(I64) | bsatn(I128) | bsatn(I256)
| bsatn(F32) | bsatn(F64)
Algebraic values include sums, products, arrays, strings, and primitives types. The primitive types include booleans, unsigned and signed integers up to 256-bits, and floats, both single and double precision.
SumValue
An instance of a sum type, i.e. an enum or tagged union.
SumValues are binary-encoded as bsatn(tag) ++ bsatn(variant_data)
where tag: u8 is an index into the SumType.variants
array of the value's SumType,
and where variant_data is the data of the variant.
For variants holding no data, i.e., of some zero sized type,
bsatn(variant_data) = [].
ProductValue
An instance of a product type, i.e. a struct or tuple.
ProductValues are binary encoded as:
bsatn(elems) = bsatn(elem_0) ++ .. ++ bsatn(elem_n)
Field names are not encoded.
ArrayValue
The encoding of an ArrayValue is:
bsatn(ArrayValue(a))
= bsatn(len(a) as u32)
++ bsatn(normalize(a)_0)
++ ..
++ bsatn(normalize(a)_n)
where normalize(a) for a: ArrayValue converts a to a list of AlgebraicValues.
Strings
For strings, the encoding is defined as:
bsatn(String(s)) = bsatn(len(s) as u32) ++ bsatn(utf8_to_bytes(s))
That is, the BSATN encoding is the concatenation of
- the bsatn of the string's length as a
u32integer byte - the utf8 representation of the string as a byte array
Primitives
For the primitive variants of AlgebraicValue, the BSATN encodings are:s
bsatn(Bool(false)) = [0]
bsatn(Bool(true)) = [1]
bsatn(U8(x)) = [x]
bsatn(U16(x: u16)) = to_little_endian_bytes(x)
bsatn(U32(x: u32)) = to_little_endian_bytes(x)
bsatn(U64(x: u64)) = to_little_endian_bytes(x)
bsatn(U128(x: u128)) = to_little_endian_bytes(x)
bsatn(U256(x: u256)) = to_little_endian_bytes(x)
bsatn(I8(x: i8)) = to_little_endian_bytes(x)
bsatn(I16(x: i16)) = to_little_endian_bytes(x)
bsatn(I32(x: i32)) = to_little_endian_bytes(x)
bsatn(I64(x: i64)) = to_little_endian_bytes(x)
bsatn(I128(x: i128)) = to_little_endian_bytes(x)
bsatn(I256(x: i256)) = to_little_endian_bytes(x)
bsatn(F32(x: f32)) = bsatn(f32_to_raw_bits(x)) // lossless conversion
bsatn(F64(x: f64)) = bsatn(f64_to_raw_bits(x)) // lossless conversion
bsatn(String(s)) = bsatn(len(s) as u32) ++ bsatn(bytes(s))
Where
f32_to_raw_bits(x)extracts the raw bits ofx: f32tou32f64_to_raw_bits(x)extracts the raw bits ofx: f64tou64
Types
All SATS types are BSATN-encoded by converting them to an AlgebraicValue,
then BSATN-encoding that meta-value.
See the SATN JSON Format for more details of the conversion to meta values. Note that these meta values are converted to BSATN and not JSON.