#[macro_export]
macro_rules! fields {
(
$(
$buffer_type:path [$raw_data:ident] {
$(
$field:tt [$position_start:literal $(..= $position_end:literal)? , $rw:tt, $value_type:tt $(<$generic:tt>)?] $({
$(input_converter:$input_converter:expr;)?
$(output_converter:$output_converter:expr)?
})?
),+ $(,)?
}
)+
) => {
$(
$(
impl $crate::field::Field<$buffer_type> for $field {
type ValueType = $value_type $(<$generic>)?;
}
$crate::fields!(
__ops: $rw, $buffer_type, $value_type, $field, $raw_data, $position_start $(..= $position_end)? $(
$(input_converter:$input_converter;)?
$(output_converter:$output_converter;)?
)?
);
)+
)+
};
(__ops: ro, $buffer_type:ty, $value_type:tt, $field:ident, $raw_data:ident, $position_start:literal $(..= $position_end:literal)?
$(output_converter:$output_converter:expr)?
) => {
impl $crate::field::FieldReader<$buffer_type> for $field {
#[inline]
fn read(buffer: &$buffer_type) -> Self::ValueType {
use $crate::IntoBits;
use $crate::BitsOps;
let x = buffer.$raw_data.bits($position_start $(..= $position_end)?).read();
let y = $crate::fields!{
__output_converter: x, $value_type $(,$output_converter)?
};
y
}
}
};
(__ops: rw, $buffer_type:path, $value_type:tt, $field:ident, $raw_data:ident, $position_start:literal $(..= $position_end:literal)?
$(input_converter:$input_converter:expr;)?
$(output_converter:$output_converter:expr;)?
) => {
$crate::fields!{
__ops: ro, $buffer_type, $value_type, $field, $raw_data, $position_start $(..= $position_end)? $(output_converter:$output_converter)?
}
impl $crate::field::FieldWriter<$buffer_type> for $field {
#[inline]
fn write(buffer: &mut $buffer_type, value: Self::ValueType){
use $crate::IntoBits;
use $crate::BitsOps;
buffer.$raw_data = buffer.$raw_data.bits($position_start $(..= $position_end)?).write(
$crate::fields!{
__input_converter: value, $value_type $(,$input_converter)?
}
);
}
#[inline]
fn revert(buffer: &mut $buffer_type) {
use $crate::IntoBits;
use $crate::BitsOps;
buffer.$raw_data = buffer.$raw_data.bits($position_start $(..= $position_end)?).revert();
}
}
};
(__output_converter: $var:ident, bool) => {
($var == 1)
};
(__output_converter: $var:ident, $value_type:tt) => {
$var as $value_type
};
($__converter:tt: $var:ident, $value_type:tt) => {
$var.into()
};
($__converter:tt: $var:ident, $value_type:tt, $converter:expr) => {
$converter($var)
};
}
#[macro_export]
macro_rules! fields_ex {
(
$(
$buffer_type:path [$raw_data:ident] {
$(
$(#[$doc:meta])*
$Vis:vis $field:ident [$position_start:literal $(..= $position_end:literal)? , $rw:tt, $value_type:tt $(<$generic:tt>)?] $({
$(input_converter:$input_converter:expr;)?
$(output_converter:$output_converter:expr)?
})?
),+ $(,)?
}
)+
) => {
$(
$(
$(#[$doc])*
$Vis struct $field;
impl $crate::field::Field<$buffer_type> for $field {
type ValueType = $value_type $(<$generic>)?;
}
$crate::fields!(
__ops: $rw, $buffer_type, $value_type, $field, $raw_data, $position_start $(..= $position_end)? $(
$(input_converter:$input_converter;)?
$(output_converter:$output_converter;)?
)?
);
)+
)+
};
}
pub trait BufferWriter {
fn write<T>(&mut self, value: T::ValueType) -> &mut Self
where
T: Field<Self> + FieldWriter<Self>,
{
T::write(self, value);
self
}
fn revert<T>(&mut self) -> &mut Self
where
T: Field<Self> + FieldWriter<Self>,
{
T::revert(self);
self
}
}
pub trait BufferReader {
fn read<T: Field<Self> + FieldReader<Self>>(&self) -> T::ValueType {
T::read(self)
}
fn output<T: Field<Self> + FieldReader<Self>>(&self, out: &mut T::ValueType) -> &Self {
*out = T::read(self);
self
}
}
pub trait Field<BufferType>
where
BufferType: ?Sized,
{
type ValueType;
}
pub trait FieldWriter<BufferType>: Field<BufferType>
where
BufferType: ?Sized,
{
fn write(buffer: &mut BufferType, value: Self::ValueType);
fn revert(buffer: &mut BufferType);
}
pub trait FieldReader<BufferType>: Field<BufferType>
where
BufferType: ?Sized,
{
fn read(buffer: &BufferType) -> Self::ValueType;
}