The Simple Compact Transaction Protocol (SCTP) library provides a highly efficient and straightforward binary serialization format, based on the LIP-0006. It is designed for performance and ease of use, especially in resource-constrained environments like WebAssembly.
The library allows you to encode a sequence of typed data fields into a compact byte stream and then decode that stream back into its original data structures. It is written in C and exposes a simple, clean API for both encoding and decoding operations.
The encoder uses a global singleton design. You initialize it once, add all your data fields sequentially, and then retrieve the final byte buffer. This model simplifies the process of creating a data stream, as you do not need to manage encoder instances.
The library offers two distinct models for decoding a byte stream, allowing you to choose the best fit for your application's architecture.
Stateful Iteration (Pull-style): This is an instance-based approach where you create a decoder for a specific data buffer. You then call sctp_decoder_next()
in a loop to "pull" data fields one by one. After each call, the decoder instance is updated with the type, value, and size of the decoded field. This model gives the caller full control over the decoding loop.
Callback-Based (Push-style): This model is ideal for WebAssembly or event-driven systems. You provide a handler function, and the decoder parses the entire stream, "pushing" each decoded field to your callback as it's found. This is driven by a single call to sctp_decoder_run()
.
SCTP uses a well-defined binary format where each data field is prefixed with a 1-byte header that specifies its type and metadata. All multi-byte integers and floats are encoded in little-endian byte order. For complete details on the binary layout, see the SCTP Encoding Specification.
This example demonstrates the full lifecycle of encoding data and then decoding it using the Stateful Iteration model.
These are the core data structures you will interact with when using the SCTP library.
sctp_type_t
An enum that defines all possible data types in an SCTP stream.
sctp_value_t
A union that holds the value of a decoded field. You must access the correct member based on the field's sctp_type_t
.
sctp_decoder_t
A struct that holds the complete state of a decoder instance. When using the stateful iteration model, you will primarily access its public fields to get information about the last decoded item.
The library is designed to integrate seamlessly with WebAssembly hosts. The primary integration point is the callback-based decoder.
When compiling the library for a Wasm environment that uses the callback model, you must define SCTP_HANDLER_PROVIDED
.
SCTP_HANDLER_PROVIDED
: This preprocessor macro signals that the host environment (e.g., JavaScript) will provide the implementation for the data handler callback. This prevents the default (dummy) implementation from being compiled.The host environment must implement and export a function with the following signature. The SCTP decoder will call this function for every data field it successfully parses from the stream.
The encoder operates on a global internal state.
sctp_encoder_init
Initializes or resets the global encoder with a new buffer of a specified capacity.
capacity
: The total size in bytes to allocate for the encoding buffer.sctp_encoder_data
Gets a read-only pointer to the start of the encoded data buffer.
const
pointer to the byte buffer.sctp_encoder_size
Gets the current size (number of bytes written) of the encoded data.
sctp_encoder_add_*
FunctionsThese functions append data of a specific type to the stream.
Function Signature | Description |
---|---|
void sctp_encoder_add_int8(int8_t v) |
Appends an 8-bit signed integer. |
void sctp_encoder_add_uint8(uint8_t v) |
Appends an 8-bit unsigned integer. |
void sctp_encoder_add_int16(int16_t v) |
Appends a 16-bit signed integer. |
void sctp_encoder_add_uint16(uint16_t v) |
Appends a 16-bit unsigned integer. |
void sctp_encoder_add_int32(int32_t v) |
Appends a 32-bit signed integer. |
void sctp_encoder_add_uint32(uint32_t v) |
Appends a 32-bit unsigned integer. |
void sctp_encoder_add_int64(int64_t v) |
Appends a 64-bit signed integer. |
void sctp_encoder_add_uint64(uint64_t v) |
Appends a 64-bit unsigned integer. |
void sctp_encoder_add_uleb128(uint64_t v) |
Appends a ULEB128-encoded integer. |
void sctp_encoder_add_sleb128(int64_t v) |
Appends an SLEB128-encoded integer. |
void sctp_encoder_add_float32(float v) |
Appends a 32-bit float. |
void sctp_encoder_add_float64(double v) |
Appends a 64-bit float (double). |
void sctp_encoder_add_eof(void) |
Appends an End-Of-File marker. |
sctp_encoder_add_short
Appends a small integer (0-15) to the stream, encoded in a single byte.
value
: The integer to encode. Must be <= 15.sctp_encoder_add_vector
Appends a variable-length byte array to the stream.
length
: The size of the vector in bytes.length
bytes to this location (e.g., using memcpy
).Example:
sctp_decoder_from_buffer
Creates a new decoder instance that reads from an existing, externally managed buffer.
buffer
: A pointer to the data buffer to decode.size
: The size of the buffer in bytes.sctp_decoder_t
instance, or NULL
on failure.sctp_decoder_init
Creates a new decoder instance and allocates a writable data buffer within the Wasm module's memory. This is primarily for hosts that need to write data into the module before decoding.
size
: The size of the data buffer to allocate.sctp_decoder_t
instance, or NULL
on failure.sctp_decoder_free
Frees a decoder instance created by sctp_decoder_from_buffer
or sctp_decoder_init
.
dec
: The decoder instance to free.This model uses sctp_decoder_next
to read one field at a time.
sctp_decoder_next
Decodes the next field from the stream and updates the decoder instance's last_type
, last_value
, and last_size
fields.
dec
: The decoder instance.sctp_type_t
of the decoded field, or SCTP_TYPE_EOF
when the end of the stream is reached.Example:
This model uses sctp_decoder_run
to parse the entire stream and invoke a callback for each field.
sctp_decoder_run
Runs the decoder over the entire buffer, invoking the host-provided __sctp_data_handler
for each field.
dec
: The decoder instance.0
on success, non-zero on error.Example (Host-side C code):