1
0
Fork 0
mirror of https://codeberg.org/icewind/bitbuffer.git synced 2026-06-03 16:44:06 +02:00

more documentation for derive

This commit is contained in:
Robin Appelman 2019-02-28 19:30:33 +01:00
commit c145761970
3 changed files with 128 additions and 34 deletions

View file

@ -1,8 +1,18 @@
//! Automatically generate `BitRead` implementations for structs //! Automatically generate `BitRead` implementations for structs and enums
//! //!
//! The implementation can be derived as long as every field in the struct implements `BitRead` or `BitReadSized` //! # Structs
//! //!
//! # Examples //! The implementation can be derived for struct as long as every field in the struct implements `BitRead` or `BitReadSized`
//!
//! The struct is read field by field in the order they are defined in, if the size for a field is set `stream.read_sized()`
//! will be used, otherwise `stream_read()` will be used.
//!
//! The size for a field can be set using 3 different methods
//! - set the size as an integer using the `size` attribute,
//! - use a previously defined field as the size using the `size` attribute
//! - read a set number of bits as an integer, using the resulting value as size using the `read_bits` attribute
//!
//! ## Examples
//! //!
//! ``` //! ```
//! use bitstream_reader_derive::BitRead; //! use bitstream_reader_derive::BitRead;
@ -23,6 +33,42 @@
//! previous_field: u8, //! previous_field: u8,
//! } //! }
//! ``` //! ```
//!
//! # Enums
//!
//! The implementation can be derived for enums as long as every variant of the enums either has no field, or an unnamed field that implements `BitRead`
//!
//! The enum is read by first reading a set number of bits as the discriminant of the enum, then the variant for the read discriminant is read.
//!
//! The discriminant for the variants defaults to incrementing by one for every field, starting with `0`.
//! You can overwrite the discriminant for a field, which will also change the discriminant for every following field.
//!
//! ## Examples
//!
//! ```
//! # use bitstream_reader_derive::BitRead;
//! #
//! #[derive(BitRead)]
//! #[discriminant_bits = 2]
//! enum TestBareEnum {
//! Foo,
//! Bar,
//! Asd = 3, // manually set the discriminant value for a field
//! }
//! ```
//!
//! ```
//! # use bitstream_reader_derive::BitRead;
//! #
//! #[derive(BitRead)]
//! #[discriminant_bits = 2]
//! enum TestUnnamedFieldEnum {
//! Foo(i8),
//! Bar(bool),
//! #[discriminant = 3] // since rust only allows setting the discriminant on field-less enums, you can use an attribute instead
//! Asd(u8),
//! }
//! ```
extern crate proc_macro; extern crate proc_macro;
use proc_macro2::{Span, TokenStream}; use proc_macro2::{Span, TokenStream};
@ -154,7 +200,7 @@ fn parse(data: &Data, struct_name: &Ident, attrs: &Vec<Attribute>) -> TokenStrea
Fields::Unit => quote_spanned! {span=> Fields::Unit => quote_spanned! {span=>
#struct_name::#variant_name #struct_name::#variant_name
}, },
Fields::Unnamed(f) => quote_spanned! {span=> Fields::Unnamed(_) => quote_spanned! {span=>
#struct_name::#variant_name(stream.read()?) #struct_name::#variant_name(stream.read()?)
}, },
_ => unimplemented!() _ => unimplemented!()

View file

@ -1,4 +1,4 @@
use bitstream_reader::{BigEndian, BitBuffer, BitStream, LittleEndian, ReadError}; use bitstream_reader::{BigEndian, BitBuffer, BitStream, LittleEndian};
use bitstream_reader_derive::BitRead; use bitstream_reader_derive::BitRead;
#[derive(BitRead, PartialEq, Debug)] #[derive(BitRead, PartialEq, Debug)]

View file

@ -2,14 +2,24 @@ use crate::{BitStream, Endianness, Result};
/// Trait for types that can be read from a stream without requiring the size to be configured /// Trait for types that can be read from a stream without requiring the size to be configured
/// ///
/// The `BitRead` trait can be used with `#[derive]` if all fields implement `BitRead` or [`BitReadSized`], /// The `BitRead` trait can be used with `#[derive]` on structs and enums
/// when `derive`d for structs, it will read all fields in the struct in the order they are defined in.
/// If a field only implements [`BitReadSized`] then the size needs to be defined using a field attribute.
/// ///
/// # Examples /// # Structs
///
/// The implementation can be derived for struct as long as every field in the struct implements `BitRead` or [`BitReadSized`]
///
/// The struct is read field by field in the order they are defined in, if the size for a field is set [`stream.read_sized()`][read_sized]
/// will be used, otherwise [`stream_read()`][read] will be used.
///
/// The size for a field can be set using 3 different methods
/// - set the size as an integer using the `size` attribute,
/// - use a previously defined field as the size using the `size` attribute
/// - read a set number of bits as an integer, using the resulting value as size using the `read_bits` attribute
///
/// ## Examples
/// ///
/// ``` /// ```
/// use bitstream_reader::BitRead; /// use bitstream_reader_derive::BitRead;
/// ///
/// #[derive(BitRead)] /// #[derive(BitRead)]
/// struct TestStruct { /// struct TestStruct {
@ -28,7 +38,45 @@ use crate::{BitStream, Endianness, Result};
/// } /// }
/// ``` /// ```
/// ///
/// # Enums
///
/// The implementation can be derived for enums as long as every variant of the enums either has no field, or an unnamed field that implements `BitRead`
///
/// The enum is read by first reading a set number of bits as the discriminant of the enum, then the variant for the read discriminant is read.
///
/// The discriminant for the variants defaults to incrementing by one for every field, starting with `0`.
/// You can overwrite the discriminant for a field, which will also change the discriminant for every following field.
///
/// ## Examples
///
/// ```
/// # use bitstream_reader_derive::BitRead;
/// #
/// #[derive(BitRead)]
/// #[discriminant_bits = 2]
/// enum TestBareEnum {
/// Foo,
/// Bar,
/// Asd = 3, // manually set the discriminant value for a field
/// }
/// ```
///
/// ```
/// # use bitstream_reader_derive::BitRead;
/// #
/// #[derive(BitRead)]
/// #[discriminant_bits = 2]
/// enum TestUnnamedFieldEnum {
/// Foo(i8),
/// Bar(bool),
/// #[discriminant = 3] // since rust only allows setting the discriminant on field-less enums, you can use an attribute instead
/// Asd(u8),
/// }
/// ```
///
/// [`BitReadSized`]: trait.BitReadSized.html /// [`BitReadSized`]: trait.BitReadSized.html
/// [read_sized]: struct.BitStream.html#method.read_sized
/// [read]: struct.BitStream.html#method.read
pub trait BitRead<E: Endianness>: Sized { pub trait BitRead<E: Endianness>: Sized {
/// Read the type from stream /// Read the type from stream
fn read(stream: &mut BitStream<E>) -> Result<Self>; fn read(stream: &mut BitStream<E>) -> Result<Self>;