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_tAn enum that defines all possible data types in an SCTP stream.
sctp_value_tA 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_tA 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_initInitializes 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_dataGets a read-only pointer to the start of the encoded data buffer.
const pointer to the byte buffer.sctp_encoder_sizeGets 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_shortAppends a small integer (0-15) to the stream, encoded in a single byte.
value: The integer to encode. Must be <= 15.sctp_encoder_add_vectorAppends 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_bufferCreates 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_initCreates 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_freeFrees 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_nextDecodes 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_runRuns 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):