Expand description
Variable length octet sequences.
This module provides the basic traits that allow defining types that are generic over a variable length sequence of octets. It implements these traits for most commonly used types of such sequences and provides a few additional types for use in a no-std environment. In addition, it provides a few types and traits that make it easier to access data contained in such sequences.
Traits for Octet Sequences
There are two fundamental types of octet sequences. If a sequence is of a
given size, we call it simply ‘octets.’ If the sequence is actually a
buffer into which octets can be placed, it is called an octets builder.
Octets and Octets References
There is no special trait for octets, we simply use AsRef<[u8]>
for
immutable octets or AsMut<[u8]>
if the octets of the sequence can be
manipulated (but the length is still fixed). This way, any type
implementing these traits can be used already. The trait OctetsExt
has been defined to collect additional methods that aren’t available via
plain AsRef<[u8]>
.
A reference to an octets type implements OctetsRef
. The main purpose
of this trait is to allow cheaply taking a sub-sequence, called a ‘range’,
out of the octets. For most types, ranges will be octet slices &[u8]
but
some shareable types (most notably bytes::Bytes
) allow ranges to be
owned values, thus avoiding the lifetime limitations a slice would
bring.
One type is special in that it is its own octets reference: &[u8]
,
referred to as an octets slice in the documentation. This means that you
always use an octets slice irregardless whether a type is generic over
an octets sequence or an octets reference. Because an octets slice is
also a useful basis when only looking at some value without planning on
keeping any ranges from it, most generic types provide a method
for_slice
that converts the value from whatever octets type it is
currently generic over into an identical value atop a octets slice of
that sequence.
The trait is separate because of limitations of lifetimes in traits. It
has an associated type OctetsRef::Range
that defines the type of a
range. When using the trait as a trait bound for a generic type, you will
typically bound a reference to this type. For instance, a generic function
taking part out of some octets and returning a reference to it could be
defined like so:
fn take_part<'a, Octets>(
src: &'a Octets
) -> <&'a Octets as OctetsRef>::Range
where &'a Octets: OctetsRef {
unimplemented!()
}
The where clause demands that whatever octets type is being used, a reference to it must be an octets ref. The return value refers to the range type defined for this octets ref. The lifetime argument is necessary to tie all these references together.
Octets Builders
Octets builders and their OctetsBuilder
trait are comparatively
straightforward. They represent a buffer to which octets can be appended.
Whether the buffer can grow to accommodate appended data depends on the
underlying type. Because it may not, all such operations may fail with a
ShortBuf
error.
The EmptyBuilder
trait marks a type as being able to create a new,
empty builder.
Conversion Traits
A series of special traits allows converting octets into octets builder and vice versa. They pair octets with their natural builders via associated types. These conversions are always cyclic, i.e., if an octets value is converted into a builder and then that builder is converted back into an octets value, the initial and final octets value have the same type.
Using Trait Bounds
When using these traits as bounds for generic types, always limit yourself to the most loose bounds you can get away with. Not all types holding octet sequences can actually implement all these traits, so by being to eager you may paint yourself into a corner.
In many cases you can get away with a simple AsRef<[u8]>
bound. Only use
an explicit OctetsRef
bound when you need to return a range that may be
kept around.
Serde Support
Serde supports native serialization of octets
sequences. However, because of missing specialization, it has to
serialize the octets slices and vec as literal sequences of u8
s. If
built with the serde
feature enable, the two traits
SerializeOctets
and DeserializeOctets
let types define serialization into octets
sequences. Types that are generic over octets sequences can use these to
implement serde’s Serialize
and Deserialize
traits.
Composing and Parsing
Octet sequences are often used to encode data, such as with the DNS wire format. We call the process of converting data into its octet sequence encoding ‘composing’ and the reverse process of reading data out of its encoded form ‘parsing.’ In order to make implementing these functions easier, the module contains a traits for types that can be composed or parsed as well as helper types for parsing.
Composing
Composing encoded data always happens directly into an octets builder.
Any type that can be encoded as DNS wire data implements the Compose
trait through which its values can be appened to the builder.
Parsing
Parsing is a little more complicated since encoded data may very well be
broken or ambiguously encoded. The helper type Parser
wraps an octets
ref and allows to parse values from the octets. The trait Parse
is
implemented by types that can decode values from octets.
Octet Sequences for no_std
Use
When using the crate without an allocator, creating octets sequences can
be difficult. However, since DNS data is often limited in size, you can in
many cases get away with using a octets array as the basis for an octets
sequence. The crate provides a macro [octets_array!
] to define such a
type for specific array length. The octets module also contains a number
of types defined via that module for typical array sizes.
Structs
- A formatting error occured.
- A fixed length octet buffer.
- A fixed length octet buffer.
- A fixed length octet buffer.
- A fixed length octet buffer.
- A fixed length octet buffer.
- A fixed length octet buffer.
- A fixed length octet buffer.
- A fixed length octet buffer.
- A parser for sequentially extracting data from an octets sequence.
- An attempt was made to write beyond the end of a buffer.
Enums
- An error happened while parsing data.
Traits
- A type that knows how to compose itself into an octets builder.
- An octets builder that can be newly created empty.
- An octets type that can be created from an octets builder.
- An octets type that can be converted into an octets builder.
- A buffer to construct an octet sequence.
- An extension trait for octet sequences.
- Convert a type from one octets type to another.
- Convert a type from one octets type to another.
- A reference to an octets sequence.
- A type that can extract a value from a parser.
Type Definitions
- A octets vector that doesn’t allocate for small sizes.