quic-codec
Utilities for decoding and encoding values in a safe and performance-oriented way.
This is an internal crate used by s2n-quic. The API is not currently stable and should not be used directly.
Decoder
Consider the following code:
decode_u8; // => (1, &[2, 3])
decode_u8; // => (4, &[])
While this is safe as far as Rust is concerned, this method will panic on missing input:
decode_u8 // thread 'main' panicked at 'index out of bounds: the len is 0 but the index is 0'
These kind of issues can be hard to detect and can have a large impact on environments like servers where untrusted data is being passed. An attacker could potentially craft a payload that will crash the server.
One possible way to mitigate these issues is to perform a check:
decode_u8; // => Ok((1, &[2, 3]))
decode_u8; // => Ok((4, &[]))
decode_u8; // => Err(Error::OutOfBounds)
This solution works for this particular case but is error-prone, as it requires each access to the slice to assert its set of preconditions. Special care especially needs to be taken when the length of a decoded value depends on a previously decoded, untrusted input:
quic-codec
instead provides an interface to a slice that is guaranteed not to
panic. It accomplishes this by forcing checks to occur and precondition
violations to be handled.
Another major advantage is gained through type-inferred decoding. The
DecoderBuffer::decode
function can be extended to support any type, given it
implements the DecoderValue
trait. Consider the following example where the
same decode
function call is used to parse u32
, u8
, and Date
itself:
Encoder
The EncoderBuffer is the counterpart to DecoderBuffer. It writes any value that
implements the EncoderValue
to a pre-allocated mutable slice. Each type gives
hints for the final the encoding size to ensure a single allocation when
encoding a value.