Expand description
Encoding and decoding support for FIDL.
This crate provides a number of types and traits related to encoding and decoding FIDL types:
§Encoding
Here, “encoding” refers to the process of converting a Rust value to an encoded FIDL message.
This process is captured in the Encode
trait, which is parameterized over an encoder.
§Encodable types
Encoding a type relies on two primary traits:
Encodable
is the most fundamental trait for encodable types. It specifies the encoded form of the type with the associatedEncoded
type. That encoded form is its wire type which must implementWire
.- Whereas
Encodable
specifies the wire type something encodes into,Encode
does the actual encoding.Encode
is parameterized over the encoder used to encode the type.
These traits are all you need to encode basic FIDL values. For more specialized encoding, some types may implement these specialized encoding traits as well:
§Encoding optional types
EncodableOption
is a variant of Encodable
which specifies how optional values of a type
should be encoded. Most FIDL types are boxed when optional, which places the encoded
value out-of-line. However, optional strings, vectors, unions, and handles are not boxed when
optional. Instead, they have special optional wire types like WireOptionalString
and
WireOptionalVector
which are optimized to save space on the wire. Implementing
EncodableOption
allows Option
s of a type to be encoded.
Implementing EncodableOption
is optional, and only required if you encode an Option
of
your type. The generated bindings will always generate an implementation of EncodableOption
for its types.
EncodeOption
is the variant of Encode
for EncodableOption
.
§Encoding by reference
EncodeRef
is a variant of Encode
for types which can be encoded by reference. Encode
encodes by value - it consumes the value being encoded. This allows Encode
to encode
resource types, which cannot be duplicated because they contain resources like handles. By
contrast, EncodeRef
does not consume the value being encoded, and can only be implemented
for non-resource types. EncodeRef
allows for more flexible and efficient encoding for many
types.
Optional types can also support encoding by reference with the EncodeOptionRef
trait.
§Encoders
Encodable types may only support encoding with specific kinds of encoders. They express these
constraints by bounding the E
type when implementing Encode<E>
to require that the encoder
implements some important traits. This crate provides the most fundamental encoder traits:
- Most FIDL types require encoders to implement
Encoder
so that they can write out-of-line data. Strings, vectors, and tables are all examples of types which write out-of-line data. TheEncoderExt
extension trait provides useful methods for encoders when it is brought into scope (use fidl_next::EncoderExt as _
). - Types containing Fuchsia handles can only be encoded by encoders which implement
HandleEncoder
. - The
InternalHandleEncoder
trait is an implementation detail. FIDL envelopes, which are used by tables and unions, may contain encoded types that the decoder doesn’t recognize. If a decoder encounters an envelope containing a type it doesn’t recognize, it needs to ignore the data and skip any handles it contained. To skip the correct number of handles, envelopes need to track the number of handles their value encoded. This is the case even if the envelope doesn’t contain any types which contain handles.InternalHandleEncoder
provides this functionality to envelopes without requiring the encoder to actually support encoding handles.
An implementation of Encoder
is provided for Vec<Chunk>
.
§Decoding
Here, “decoding” has a very specific meaning. It refers to the process of validating and
rewriting a buffer of Chunk
s to ensure it contains a valid Wire
type. This definition is
narrow, and does not include converting a wire type to a natural type.
The process of decoding is captured in the Decode
trait. Like encoding, Decode
is
parameterized over a decoder.
§Decodable types
Types which implement Decode
must first implement Wire
to guarantee that their
representation conforms to the requirements of the FIDL wire format specification. Then, they
can specify how to validate and decode their wire form with the decode
method.
decode
needs to do three things to be correct:
- Verify that the encoded bytes are valid for the type. For
bool
s, this means verifying that the encoded byte is either exactly 0 or exactly 1. If the encoded bytes are not valid for the type,decode
must return an error. - Reify pointers by decoding any out-of-line data and replacing presence indicators with the value of a pointer to that decoded data.
- Move resources from the decoder into the buffer. On the wire, handles are replaced with a presence indicator. They are transported separately by the transport because they require special handling.
Note that decode
only manipulates data in-place, and only returns whether it
succeeded or failed.
§Decoders
Like encoding, some types may only support encoding with specific types of decoders. We express
these constraints by bounding the D
type when implementing Decode<D>
to require that the
decoder implements some important traits:
- Most FIDL types require decoders to implement
Decoder
so that they can decode out-of-line data. TheDecoderExt
extension trait provides useful methods for decoders when it is brought into scope (use fidl_next::DecoderExt as _
). - Types containing Fuchsia handles can only be decoded by decoders which implement
HandleDecoder
. - Like encoding, the
InternalHandleDecoder
trait is an implementation detail for FIDL envelopes.
An implementation of Decoder
is provided for &mut [Chunk]
.
§Committing
Decoding a wire type can fail at any point, even after resources have been taken out of the decoder. This presents a problem: partially-decoded values cannot be dropped, but may contain resources that must be dropped.
To solve this problem, taking a resource from a decoder happens in two phases:
- While decoding the resource is copied from the decoder into the buffer. The resource is left in the decoder.
- After decoding finishes successfully, the decoder is committed. Calling
commit
semantically completes moving the resources from the decoder into the buffer.
If decoding fails before commit
is called, the decoder remains responsible for dropping the
taken resources. After commit
is called, the wire value is responsible for dropping the taken
resources.
§Wire types
FIDL types which are used in-place without copying them out of the buffer implement Wire
and
are called “wire types”. Wire
is an unsafe trait which bundles together the necessary
guarantees and functional machinery for wire types. The most important thing it does is promise
that the implementing type follows any layout requirements for FIDL’s wire types.
§Primitives
The FIDL wire specification requires “natural alignment” for wire primitives, which means that
wire primitives must have alignment equal to their size. A four-byte int32
must be
four-aligned, and so may differ from Rust’s native i32
type. To accommodate these differences,
multibyte primitive types have special wire forms. Single-byte primitive types have the same
natural and wire types.
FIDL type | Natural type | Wire type |
---|---|---|
bool | bool | bool |
int8 | i8 | i8 |
int16 | i16 | WireI16 |
int32 | i32 | WireI32 |
int64 | i64 | WireI64 |
uint8 | u8 | u8 |
uint16 | u16 | WireU16 |
uint32 | u32 | WireU32 |
uint64 | u64 | WireU64 |
float32 | f32 | WireF32 |
float64 | f64 | WireF64 |
All wire primitives implement Deref
and dereference to their native primitive types.
§Containers
This crate provides wire types for containers supported by FIDL:
FIDL type | Natural type | Wire type |
---|---|---|
box<T> | Option<T> | WireBox<T> |
array<T, N> | [T; N] | [T; N] |
vector<T> | Vec<T> | WireVector<T> |
string | String | WireString |
§Lifetimes
Wire types with out-of-line data may contain pointers to other parts of a decoded buffer, and so
cannot be allowed to outlive that decoded buffer. As a result, wire types are parameterized over
the lifetime of the decoder they are contained in (typically named 'de
). This lifetime isn’t
important when reading data with wire types, but can impose important constraints when moving
wire types and converting them to natural types.
After decoding, shared references to wire types can be obtained and used without any restrictions. These shared references allow reading the data from wire types, and provide all of the functionality required for handle-less FIDL.
However, in order to move resources like handles out of wire types, wire values must be taken from the decoder. Taking a wire type out of a decoder is an all-or-nothing operation - you must take the entire decoded wire value from a decoder, and it must be moved or dropped before the decoder can be moved or dropped. You can think of taking the wire value as sticking the decoder in place until the wire value is converted to a natural type or dropped. This means that for FIDL protocols, you must take the entire received FIDL message.
When wire values are taken out of a decoder, they are parameterized over the lifetime of the
decoder (usually 'de
) to prevent the decoder from being dropped. These values can be treated
like ordinary Rust values.
§Conversion to natural types
Natural types can support conversion from a wire type by implementing FromWire
. This trait
has a from_wire
method which parallels From::from
and implements
conversion from some wire type. Like Encode
and Decode
, the FromWireOption
variant
allows types to be converted from wire optional types.
Natural types that can be converted from a reference to a wire type (i.e. without moving the
wire type) may implement FromWireRef
. Similarly for options, the FromWireOptionRef
trait
allows options to be converted from a reference to a wire type.
Re-exports§
pub use self::decoder::Decoder;
pub use self::decoder::DecoderExt;
pub use self::encoder::Encoder;
pub use self::encoder::EncoderExt;
Modules§
- decoder
- The core
Decoder
trait. - encoder
- The core
Encoder
trait. - fuchsia
- Fuchsia-specific extensions to the FIDL codec.
Macros§
- bitflags
- Generate a flags type.
- chunks
- Returns a slice of chunks with the same bytewise value as the given bytes.
- munge
- Destructures a type into
Structs§
- Copy
Optimization - An optimization hint about whether the conversion from
T
toU
is equivalent to copying the raw bytes ofT
. - Decoded
- A decoded value and the decoder which contains it.
- Into
Iter - An iterator over the items of a
WireVector
. - RawWire
Union - A raw FIDL union
- Slot
- An initialized but potentially invalid value.
- WireBox
- A boxed (optional) FIDL value.
- WireF32
- A wire-encoded
f32
- WireF64
- A wire-encoded
f64
- WireI16
- A wire-encoded
i16
- WireI32
- A wire-encoded
i32
- WireI64
- A wire-encoded
i64
- Wire
Optional String - An optional FIDL string
- Wire
Optional Vector - An optional FIDL vector
- Wire
Result - A FIDL result union.
- Wire
String - A FIDL string
- Wire
Table - A FIDL table
- WireU16
- A wire-encoded
u16
- WireU32
- A wire-encoded
u32
- WireU64
- A wire-encoded
u64
- Wire
Vector - A FIDL vector
Enums§
- Decode
Error - Errors that can be produced when decoding FIDL messages.
- Encode
Error - Errors that can be produced while encoding FIDL messages.
Constants§
- CHUNK_
SIZE - FIDL alignment, used for buffer alignment to ensure decoding in-place is possible.
Traits§
- Decode
- Decodes a value from the given slot.
- Encodable
- A type which can be encoded as FIDL.
- Encodable
Option - A type which can be encoded as FIDL when optional.
- Encode
- Encodes a value.
- Encode
Option - Encodes an optional value.
- Encode
Option Ref - Encodes an optional reference.
- Encode
Ref - Encodes a reference.
- From
Wire - A type which is convertible from a wire type.
- From
Wire Option - An optional type which is convertible from a wire type.
- From
Wire Option Ref - An optional type which is convertible from a reference to a wire type.
- From
Wire Ref - A type which is convertible from a reference to a wire type.
- Wire
- A FIDL wire type.
Type Aliases§
- Chunk
- A group of eight bytes, aligned to an 8-byte boundary.
Unions§
- Wire
Envelope - A FIDL envelope
- Wire
Pointer - A raw FIDL pointer