Language / platform-agnostic wire-safe linear (flat) memory rich data models.
bool
i8
u8
i16
i32
i64
i128
u16
u32
u64
u128
f32
f64
i16b
i32b
i64b
i128b
u16b
u32b
u64b
u128b
f32b
f64b
i16n
i32n
i64n
i128n
u16n
u32n
u64n
u128n
f32n
f64n
Pointers are an unsigned integer that represents the offset in the buffer where the data type resides or 0 for null.
usize16 - Supports messages <64kb
usize32 - Supports messages <4GB
usize64 - Supports messages >4GB
string
Embedded string with a max total size including length field.
string{size}
string8
Inline string with heap allocated spill-over when string size is larger than inline size.
string{size}..
string8..
variant vstring8 {
string8
string
}
[{size}]{type}
[8]i64
[]i64
Robinhood hashmap (linear probing)
map<i64, string>
ART Radix Tree
sorted_map<i64, string>
B+Tree
tree_map<i64, string>
Robinhood hashmap with no values
set<i64>
ART Radix Tree with no values
sorted_set<i64>
B+Tree with no values
tree_set<i64>
enum Code : i32 {
SUCCESS = 0
ERROR = 1
}
// single line using comma separator
enum Code : i32 { SUCCESS = 0, ERROR = 1}
// single line using semicolon separator
enum Code : i32 { SUCCESS = 0; ERROR = 1}
Type safe union or tagged union.
- C++ = std::variant
- Rust = enum
- Kotlin = sealed class
variant Value {
i64
f64
string8
string
// inline embedded struct
Option {
}
// inline optional struct or struct pointer
*Option {
}
}
struct Order {
uid string = "optional default value"
number u64 = 1
// inline struct
lines []struct{
number u32
quantity u32
price f64
} = [{1, 1, 9.99}]
// unions are declared inline and support multiple levels of nesting
union {
w f64
x f64
union {
y f64
z f64
}
}
// inner struct = Order::Line
struct Line {
number u32
quantity u32
price f64
}
}
May only modify fixed fields OR where the update will not require the underlying buffer to be resized.
Optionally supports JSON serialization and deserialization. Can utilize WAP for in-memory structure and JSON for the wire protocol.
Optionally supports Protocol Buffers serialization and deserialization.
A WAP root message is a single contiguous chunk of memory regardless of the number of internal structures there are.
Provide field number tag '@'
struct Order {
@1 uid string
@3 new_field bool
@2 number u64
}
struct Order {
uid string
number u64
new_field bool // implicitly becomes @3
}
Fixed sized messages use Mutable Reader instead.
Messages are built in an append-only mode. Fastest.
Messages are built using an internal dynamic memory allocator with size classes and freelists. Best for highly mutable/dynamic messages.
Only pay for bounds checking when necessary.
Generated code only depends on a single header file which can be tweaked for corner use cases.
Virtual methods are never used for accessing data fields. Field access can be inlined in most cases.
Only pay for bounds checking when necessary.
- Struct - Message was built / guaranteed to conform with current generated code. No bounds checking at all. FAST!
- Reader - Perform bounds check on every access. Wire mode default.
- Reader Variant (visit) - Use a reader/builder variant for each internal struct root. Wire mode optimization. Potential partial bounds check elimination.
- Builder - No bounds checking, however for flexible messages there will likely be another pointer dereference due to underlying buffer pointer instability when resize is required. For fixed sized messages, it's the same as Struct.
- Struct - Message was built / guaranteed to conform with current generated code. No bounds checking at all. FAST!
- Reader / Mutable Reader - Perform bounds check on every access. Wire mode default.
- Builder - No bounds checking, however for flexible messages there will likely be another pointer dereference due to underlying buffer pointer instability when resize is required. For fixed sized messages, it's the same as Struct.
Go generics are non-monomorphisable for pointer types. Huge runtime performance penalty that goes against WAP core performance tenants of static over dynamic.
TinyGo is supported including WASM!