distribute/codec
Types
Encoder + decoder + sized decoder, bundled. The shared a is the
compile-time guarantee that the three sides agree on the message
type. Assemble through Codec(...) whenever you can, and only
reach for the open aliases for genuinely heterogeneous composition.
pub type Codec(a) {
Codec(
encoder: fn(a) -> Result(BitArray, EncodeError),
decoder: fn(BitArray) -> Result(a, DecodeError),
sized_decoder: fn(BitArray) -> Result(
#(a, BitArray),
DecodeError,
),
)
}
Constructors
-
Codec( encoder: fn(a) -> Result(BitArray, EncodeError), decoder: fn(BitArray) -> Result(a, DecodeError), sized_decoder: fn(BitArray) -> Result( #(a, BitArray), DecodeError, ), )
pub type DecodeError {
InvalidBinary(String)
TypeMismatch(String)
DecodeFailed(String)
InsufficientData(String)
DecodeTimeout
TagMismatch(expected: String, got: String)
VersionMismatch(expected: Int, got: Int)
PayloadTooLarge(Int)
ListTooLong(count: Int, cap: Int)
}
Constructors
-
InvalidBinary(String) -
TypeMismatch(String) -
DecodeFailed(String) -
InsufficientData(String) -
DecodeTimeout -
TagMismatch(expected: String, got: String) -
VersionMismatch(expected: Int, got: Int) -
PayloadTooLarge(Int)The received payload exceeds
config.max_payload_size_bytes. TheIntis the actual byte size of the rejected payload. -
ListTooLong(count: Int, cap: Int)The list-length prefix declares more elements than the decoder will materialise in a single frame. Defends against the “billion-laughs” amplification attack, where a 4-byte payload declares N billion zero-byte elements (e.g.
list(nil())) and crashes the receiver with OOM despite the network-level payload size cap accepting the input.
pub type Decoder(a) =
fn(BitArray) -> Result(a, DecodeError)
pub type EncodeError {
InvalidValue(String)
EncodeFailed(String)
ValueTooLarge(String)
}
Constructors
-
InvalidValue(String) -
EncodeFailed(String) -
ValueTooLarge(String)
pub type Encoder(a) =
fn(a) -> Result(BitArray, EncodeError)
Like Decoder but returns leftover bytes for chaining.
pub type SizedDecoder(a) =
fn(BitArray) -> Result(#(a, BitArray), DecodeError)
Values
pub fn bitarray_decoder() -> fn(BitArray) -> Result(
BitArray,
DecodeError,
)
pub fn bitarray_encoder() -> fn(BitArray) -> Result(
BitArray,
EncodeError,
)
pub fn bitarray_sized_decoder() -> fn(BitArray) -> Result(
#(BitArray, BitArray),
DecodeError,
)
pub fn bool_decoder() -> fn(BitArray) -> Result(Bool, DecodeError)
pub fn bool_encoder() -> fn(Bool) -> Result(BitArray, EncodeError)
pub fn bool_sized_decoder() -> fn(BitArray) -> Result(
#(Bool, BitArray),
DecodeError,
)
pub fn decode(
decoder: fn(BitArray) -> Result(a, DecodeError),
data: BitArray,
) -> Result(a, DecodeError)
pub fn decode_error_to_string(error: DecodeError) -> String
pub fn decode_sized(
decoder: fn(BitArray) -> Result(#(a, BitArray), DecodeError),
data: BitArray,
) -> Result(#(a, BitArray), DecodeError)
pub fn encode(
encoder: fn(a) -> Result(BitArray, EncodeError),
value: a,
) -> Result(BitArray, EncodeError)
pub fn encode_error_to_string(error: EncodeError) -> String
pub fn float_decoder() -> fn(BitArray) -> Result(
Float,
DecodeError,
)
pub fn float_encoder() -> fn(Float) -> Result(
BitArray,
EncodeError,
)
pub fn float_sized_decoder() -> fn(BitArray) -> Result(
#(Float, BitArray),
DecodeError,
)
pub fn int_decoder() -> fn(BitArray) -> Result(Int, DecodeError)
pub fn int_encoder() -> fn(Int) -> Result(BitArray, EncodeError)
pub fn int_sized_decoder() -> fn(BitArray) -> Result(
#(Int, BitArray),
DecodeError,
)
pub fn list_decoder(
element_decoder: fn(BitArray) -> Result(
#(a, BitArray),
DecodeError,
),
) -> fn(BitArray) -> Result(List(a), DecodeError)
pub fn list_encoder(
element_encoder: fn(a) -> Result(BitArray, EncodeError),
) -> fn(List(a)) -> Result(BitArray, EncodeError)
pub fn list_sized_decoder(
element_decoder: fn(BitArray) -> Result(
#(a, BitArray),
DecodeError,
),
) -> fn(BitArray) -> Result(#(List(a), BitArray), DecodeError)
pub fn map(
c: Codec(a),
wrap: fn(a) -> b,
unwrap: fn(b) -> a,
) -> Codec(b)
Transform a codec. wrap runs after decoding, unwrap before encoding.
pub fn nil_decoder() -> fn(BitArray) -> Result(Nil, DecodeError)
Strict top-level decoder for Nil: the wire form is zero bytes, and
any trailing data is a protocol violation (either a bug in the
sender or smuggled payload). Earlier drafts accepted the binary
regardless, defeating the strict-top-level contract that
to_decoder enforces for every other primitive.
pub fn nil_encoder() -> fn(Nil) -> Result(BitArray, EncodeError)
pub fn nil_sized_decoder() -> fn(BitArray) -> Result(
#(Nil, BitArray),
DecodeError,
)
pub fn string_decoder() -> fn(BitArray) -> Result(
String,
DecodeError,
)
pub fn string_encoder() -> fn(String) -> Result(
BitArray,
EncodeError,
)
pub fn string_sized_decoder() -> fn(BitArray) -> Result(
#(String, BitArray),
DecodeError,
)
pub fn subject() -> Codec(process.Subject(BitArray))
Subject codec, for the request/response pattern.
pub fn subject_decoder() -> fn(BitArray) -> Result(
process.Subject(BitArray),
DecodeError,
)
pub fn subject_encoder() -> fn(process.Subject(BitArray)) -> Result(
BitArray,
EncodeError,
)
Encode a Subject(BitArray) via term_to_binary. The PID
inside carries node info, so it routes back cross-node.
Mirrors the 32-bit-prefix validation in string_encoder /
bitarray_encoder / list_encoder. A Subject larger than 4 GiB
is absurd in practice (it would imply a 4 GiB tag), but the bound
is enforced for symmetry with the rest of the codec surface.
pub fn subject_sized_decoder() -> fn(BitArray) -> Result(
#(process.Subject(BitArray), BitArray),
DecodeError,
)
pub fn to_decoder(
sized: fn(BitArray) -> Result(#(a, BitArray), DecodeError),
) -> fn(BitArray) -> Result(a, DecodeError)
Turn a SizedDecoder into a top-level Decoder with strict parsing.
The frame must consume the binary completely. Any unconsumed
trailing bytes are a protocol violation (data smuggling, double
payloads, framing bug) and surface as Error(InvalidBinary("trailing bytes ...")). Earlier drafts silently dropped the leftover.
Composite codecs that need to chain frames within one binary (lists,
tuples) call the underlying SizedDecoder directly, so they keep
working as before. Only the top-level entry point is strict.