#[derive(BitEncode)]
{
// Attributes available to this derive:
#[bin_proto]
}
derive only.Expand description
Derive the BitDecode and BitEncode traits.
§Scopes
#[container, enum]
enum Enum {
#[variant]
Variant {
#[field]
field: Type,
}
}
#[container, struct]
struct Struct {
#[field]
field: Type,
}§Using Context
The ctx and ctx_bounds attributes can be used to specify additional
context used during codec. The context can be accessed as __ctx, and the tag as __tag in any
attribute macro’s <expr>, for example in tag.
struct Ctx {
n: u32,
}
#[derive(BitDecode, BitEncode)]
#[bin_proto(ctx = Ctx)]
struct WithElementsLength {
count: u32,
foo: bool,
#[bin_proto(tag = count * __ctx.n)]
data: Vec<u32>,
}§Attributes
| Attribute | Scope | Applicability |
|---|---|---|
discriminant_type | enum | rw |
discriminant | variant | rw |
other | variant | r |
bits | field, enum | rw |
untagged | field | rw |
tag | field | rw |
tag_type | field | rw |
write_value | field | w |
ctx | container | rw |
ctx_bounds | container | rw |
skip_encode | field, variant | w |
skip_decode | field, variant | r |
skip | field, variant | rw |
pad_before | field, struct | rw |
pad_after | field, struct | rw |
magic | field, struct | rw |
§discriminant_type
#[bin_proto(discriminant_type = <type>)]
Specify if enum variant should be determined by a string or interger representation of its discriminant.
#[derive(BitDecode, BitEncode)]
#[bin_proto(discriminant_type = u8)]
enum Example {
Variant1 = 1,
Variant5 = 5,
}§discriminant
#[bin_proto(discriminant = <value>)]
<value>: unique value of the discriminant’s type
Specify the discriminant for a variant.
#[derive(BitDecode, BitEncode)]
#[bin_proto(discriminant_type = u8)]
enum Example {
#[bin_proto(discriminant = 1)]
Variant1,
Variant5 = 5,
}§other
#[bin_proto(other)]
Decode the specified variant if the discriminant doesn’t match any other variants. A discriminant value can still be provided for the variant, and will be used when encoding.
#[derive(BitDecode, BitEncode)]
#[bin_proto(discriminant_type = u8)]
enum Example {
#[bin_proto(discriminant = 1)]
Variant1,
#[bin_proto(discriminant = 2, other)]
CatchAll,
}§bits
#[bin_proto(bits = <width>)]
Determine width of field in bits.
WARNING: Bitfields disregard endianness and instead have the same endianness as the
underlying BitRead / BitWrite instance. If you’re using bitfields, you almost always
want a big endian stream.
#[derive(BitDecode, BitEncode)]
struct Nibble(#[bin_proto(bits = 4)] u8);§untagged
#[bin_proto(untagged)]
Variable-length field is final field in container, hence lacks a length prefix and should be read until eof.
#[derive(BitDecode, BitEncode)]
struct ReadToEnd(#[bin_proto(untagged)] Vec<u8>);§tag
#[bin_proto(tag = <expr>)]
<expr>: arbitrary expression. Fields in parent container can be used without prefixing them withself.
Specify tag of field. The tag represents a length prefix for variable-length fields, and a
boolean for Option.
#[derive(BitDecode, BitEncode)]
struct WithElementsLength {
count: u32,
foo: bool,
#[bin_proto(tag = count as usize)]
data: Vec<u32>,
}§tag_type
#[bin_proto(tag_type = <type>[, tag_value = <expr>]?[, tag_bits = <expr>]?)]
<type>: tag’s type<expr>: arbitrary expression. Fields in parent container should be prefixed withself.
Specify tag of field. The tag represents a length prefix for variable-length fields, and a
boolean for Option. The tag is placed directly before the field. The tag_value only has
to be specified when deriving BitEncode.
#[derive(BitDecode, BitEncode)]
struct WithElementsLength {
#[bin_proto(tag_type = u16, tag_value = self.data.len() as u16, tag_bits = 13)]
data: Vec<u32>,
}§write_value
#[bin_proto(write_value = <expr>)]
<expr>: An expression that can be coerced to the field type. Fields in parent container should be prefixed withself.
Specify an expression that should be used as the field’s value for writing.
#[derive(BitDecode, BitEncode)]
struct WithElementsLengthAuto {
#[bin_proto(write_value = self.data.len() as u32)]
count: u32,
foo: bool,
#[bin_proto(tag = count as usize)]
data: Vec<u32>,
}§ctx
#[bin_proto(ctx = <type>)[, ctx_generics(<generic>[, <generic>]*)]?]
<type>: The type of the context. Either a concrete type, or one of the container’s generics<generic>: Any generics used by the context type, with optional bounds. E.g.T: Copyfor aVec<T>context.
Specify the type of context that will be passed to codec functions.
struct Ctx;
struct NeedsCtx;
impl BitDecode<Ctx> for NeedsCtx {
fn decode<R, E>(
_read: &mut R,
_ctx: &mut Ctx,
_tag: (),
) -> bin_proto::Result<Self>
where
R: bin_proto::BitRead,
E: bin_proto::Endianness,
{
// Use ctx here
Ok(Self)
}
}
impl BitEncode<Ctx> for NeedsCtx {
fn encode<W, E>(
&self,
_write: &mut W,
_ctx: &mut Ctx,
_tag: (),
) -> bin_proto::Result<()>
where
W: bin_proto::BitWrite,
E: bin_proto::Endianness,
{
// Use ctx here
Ok(())
}
}
#[derive(BitDecode, BitEncode)]
#[bin_proto(ctx = Ctx)]
struct WithCtx(NeedsCtx);
WithCtx(NeedsCtx)
.encode_bytes_ctx(bin_proto::BigEndian, &mut Ctx, ())
.unwrap();#[derive(BitDecode, BitEncode)]
#[bin_proto(ctx = Ctx)]
struct NestedCodec<Ctx, A: BitDecode<Ctx> + BitEncode<Ctx>>(A, PhantomData<Ctx>);struct Ctx<'a, T: Copy>(&'a T);
#[derive(BitDecode, BitEncode)]
#[bin_proto(ctx = Ctx<'a, T>, ctx_generics('a, T: Copy))]
struct WithCtx;§ctx_bounds
#[bin_proto(ctx_bounds(<bound>[, <bound>]*)[, ctx_generics(<generic>[, <generic>]*)]?)]
<bounds>: Trait bounds that must be satisfied by the context<generic>: Any generics used by the context type. E.g.'afor a context with aFrom<&'a i32>bound.
Specify the trait bounds of context that will be passed to codec functions.
trait CtxTrait {};
struct NeedsCtx;
impl<Ctx: CtxTrait> BitDecode<Ctx> for NeedsCtx {
fn decode<R, E>(
_read: &mut R,
_ctx: &mut Ctx,
_tag: (),
) -> bin_proto::Result<Self>
where
R: bin_proto::BitRead,
E: bin_proto::Endianness,
{
// Use ctx here
Ok(Self)
}
}
impl<Ctx: CtxTrait> BitEncode<Ctx> for NeedsCtx {
fn encode<W, E>(
&self,
_write: &mut W,
_ctx: &mut Ctx,
_tag: (),
) -> bin_proto::Result<()>
where
W: bin_proto::BitWrite,
E: bin_proto::Endianness,
{
// Use ctx here
Ok(())
}
}
#[derive(BitDecode, BitEncode)]
#[bin_proto(ctx_bounds(CtxTrait))]
struct WithCtx(NeedsCtx);#[derive(BitDecode, BitEncode)]
#[bin_proto(ctx_bounds(From<&'a i32>), ctx_generics('a))]
struct WithCtx;§skip_encode
#[bin_proto(skip_encode)]
If applied to a field, skip the field when encoding. If applied to an enum variant, return an Error if the variant is attempted to be encoded.
#[derive(BitDecode, BitEncode)]
struct Struct(#[bin_proto(skip_encode)] u8);#[derive(BitEncode)]
#[bin_proto(discriminant_type = u8)]
enum Enum {
#[bin_proto(skip_encode)]
Skip
}§skip_decode
#[bin_proto(skip_decode)]
If applied to a field, use Default::default instead of attempting to read field. If applied
to an enum variant, don’t generate code for decoding.
#[derive(BitDecode, BitEncode)]
struct Struct(#[bin_proto(skip_decode)] u8);#[derive(BitDecode)]
#[bin_proto(discriminant_type = u8)]
enum Enum {
#[bin_proto(skip_decode)]
Skip
}§skip
#[bin_proto(skip)]
Equivalent to combining skip_encode and skip_decode.
#[derive(BitDecode, BitEncode)]
struct Struct(#[bin_proto(skip)] u8);#[derive(BitDecode, BitEncode)]
#[bin_proto(discriminant_type = u8)]
enum Enum {
#[bin_proto(skip)]
Skip
}§pad_before
#[bin_proto(pad_before = <expr>)]
Insert 0 bits when writing and skip bits when reading, prior to processing the field.
#[derive(BitDecode, BitEncode)]
struct Struct(#[bin_proto(pad_before = 3)] u8);§pad_after
#[bin_proto(pad_after = <expr>)]
Insert 0 bits when writing and skip bits when reading, after processing the field.
#[derive(BitDecode, BitEncode)]
struct Struct(#[bin_proto(pad_after = 3)] u8);§magic
#[bin_proto(magic = <expr>)]
<expr>: Must evaluate to&[u8; _]
Indicates that the value must be present immediately preceding the field or struct.
#[derive(BitDecode, BitEncode)]
#[bin_proto(magic = &[0x01, 0x02, 0x03])]
struct Magic(#[bin_proto(magic = b"123")] u8);