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.