erg_bits/
field.rs

1/// 用于为含有 bit field 的结构体中的 bit 字段实现
2/// [`Field`]、[`FieldReader`]、[`FieldWriter`] 接口。
3/// 具体用法看示例:
4///  ```
5/// use erg_bits::field::BufferWriter;
6/// use erg_bits::field::BufferReader;
7/// use erg_bits::IntoBits;
8/// use erg_bits::BitsOps;
9///
10/// pub struct FoolData {
11///     data: u32,
12///     data1: u32,
13/// }
14/// impl BufferWriter for FoolData{}
15/// impl BufferReader for FoolData{}
16///
17/// // bit 字段 1,其余类推
18/// pub struct Flag1;
19/// pub struct Flag2;
20/// pub struct Flag3;
21/// pub struct Flag4;
22/// pub struct Flag5;
23/// pub struct Flag6;
24///
25/// erg_bits::fields! {
26///     FoolData [data] {
27///         Flag1 [0..=3, rw, u32],
28///         Flag2 [4..=5, rw, u32],
29///         Flag3 [6, ro, bool],
30///         Flag4 [7, rw, bool],
31///         Flag5 [8..=9, rw, bool] {
32///             input_converter: |x| match x {
33///                 true => 0x1,
34///                 _ => 0x0
35///             };
36///             output_converter: |x| match x {
37///                 0x1 => true,
38///                 _ => false
39///             }
40///         }
41///     }
42///     FoolData [data1] {
43///         Flag6 [0..=3, rw, u32]
44///     }
45/// }
46/// let mut fool = FoolData {data:0x0, data1: 0x0};
47/// fool.write::<Flag1>(0xf);
48/// assert_eq!(fool.data, 0xf);
49///
50/// fool.write::<Flag2>(0x3);
51/// assert_eq!(fool.data, 0b0011_1111);
52///
53/// // error: the trait `FieldWriter<FoolData>` is not implemented for `Flag3`
54/// // fool.write::<Flag3>(true); // Flag3 is not writeable
55///
56/// fool.write::<Flag4>(true);
57/// assert_eq!(fool.data, 0b1011_1111);
58///
59/// let flag3 = fool.read::<Flag3>();
60/// assert_eq!(flag3, false);
61///
62/// let flag4 = fool.read::<Flag4>();
63/// assert_eq!(flag4, true);
64///
65/// fool.data = fool.data.bits(8..=9).write(0x2); // set fool.data bits 8..=9 to 0x2
66/// assert_eq!(false, fool.read::<Flag5>()); // bits: 8..=9 equal to 0x2 which is false
67///
68/// fool.write::<Flag5>(true);
69/// assert_eq!(0b01, fool.data.bits(8..=9).read());
70/// ```
71///
72/// 值得注意的是将字段结构体定义留给程序员自行定义,
73/// 这样可以避免在同一个命名空间内,通过宏为不同的结构体定义相同的字段时,
74/// 造成重定义。
75#[macro_export]
76macro_rules! fields {
77    (
78        $(
79            $buffer_type:path [$raw_data:ident] {
80                $(
81                    $field:tt [$position_start:literal $(..= $position_end:literal)? , $rw:tt, $value_type:tt $(<$generic:tt>)?] $({
82                        $(input_converter:$input_converter:expr;)?
83                        $(output_converter:$output_converter:expr)?
84                    })?
85                ),+  $(,)?
86            }
87        )+
88    ) => {
89        $(
90            $(
91                impl $crate::field::Field<$buffer_type> for $field {
92                    type ValueType = $value_type $(<$generic>)?;
93                }
94                $crate::fields!(
95                    __ops: $rw,  $buffer_type, $value_type, $field, $raw_data, $position_start $(..= $position_end)? $(
96                        $(input_converter:$input_converter;)?
97                        $(output_converter:$output_converter;)?
98                    )?
99                );
100            )+
101        )+
102    };
103    (__ops: ro, $buffer_type:ty, $value_type:tt, $field:ident, $raw_data:ident, $position_start:literal $(..= $position_end:literal)?
104        $(output_converter:$output_converter:expr)?
105    ) => {
106        impl $crate::field::FieldReader<$buffer_type> for $field {
107            #[inline]
108            fn read(buffer: &$buffer_type) -> Self::ValueType {
109                use $crate::IntoBits;
110                use $crate::BitsOps;
111                let x = buffer.$raw_data.bits($position_start $(..= $position_end)?).read();
112                let y = $crate::fields!{
113                    __output_converter: x, $value_type $(,$output_converter)?
114                };
115                y
116            }
117        }
118    };
119    (__ops: rw, $buffer_type:path, $value_type:tt, $field:ident, $raw_data:ident, $position_start:literal $(..= $position_end:literal)?
120        $(input_converter:$input_converter:expr;)?
121        $(output_converter:$output_converter:expr;)?
122    ) => {
123        $crate::fields!{
124            __ops: ro, $buffer_type, $value_type, $field, $raw_data, $position_start $(..= $position_end)? $(output_converter:$output_converter)?
125        }
126        impl $crate::field::FieldWriter<$buffer_type> for $field {
127            #[inline]
128            fn write(buffer: &mut $buffer_type, value: Self::ValueType){
129                use $crate::IntoBits;
130                use $crate::BitsOps;
131                buffer.$raw_data = buffer.$raw_data.bits($position_start $(..= $position_end)?).write(
132                    $crate::fields!{
133                        __input_converter: value, $value_type $(,$input_converter)?
134                    }
135                );
136            }
137            #[inline]
138            fn revert(buffer: &mut $buffer_type) {
139                use $crate::IntoBits;
140                use $crate::BitsOps;
141                buffer.$raw_data = buffer.$raw_data.bits($position_start $(..= $position_end)?).revert();
142            }
143        }
144    };
145    (__output_converter: $var:ident, bool) => {
146        ($var == 1)
147    };
148    (__output_converter: $var:ident, $value_type:tt) => {
149        $var as $value_type
150    };
151    ($__converter:tt: $var:ident, $value_type:tt) => {
152        $var.into()
153    };
154    ($__converter:tt: $var:ident, $value_type:tt, $converter:expr) => {
155        $converter($var)
156    };
157}
158
159/// 相比于宏 fields,fields_ex 可以添加注释,且会自行定义字段结构体单元;
160///
161/// 注意:fields_ex 并非是任何情况的最优解。
162#[macro_export]
163macro_rules! fields_ex {
164    (
165        $(
166            $buffer_type:path [$raw_data:ident] {
167                $(
168                    $(#[$doc:meta])*
169                    $Vis:vis $field:ident [$position_start:literal $(..= $position_end:literal)? , $rw:tt, $value_type:tt $(<$generic:tt>)?] $({
170                        $(input_converter:$input_converter:expr;)?
171                        $(output_converter:$output_converter:expr)?
172                    })?
173                ),+ $(,)?
174            }
175        )+
176    ) => {
177        $(
178            $(
179                $(#[$doc])*
180                $Vis struct $field;
181                impl $crate::field::Field<$buffer_type> for $field {
182                    type ValueType = $value_type $(<$generic>)?;
183                }
184                $crate::fields!(
185                    __ops: $rw,  $buffer_type, $value_type, $field, $raw_data, $position_start $(..= $position_end)? $(
186                        $(input_converter:$input_converter;)?
187                        $(output_converter:$output_converter;)?
188                    )?
189                );
190            )+
191        )+
192    };
193}
194
195/// # Buffer 写入器
196///
197/// 通常将 bit 字段归属的结构体看作缓存。通过实现 BufferWriter 来对 bit 字段进行写入操作。
198/// bit 字段所归属的结构体需要实现该接口(如果含有任何可写 bit 字段)。
199///
200/// 👍 将 bit 字段归属的结构体看作缓存,在实现寄存器读写操作时会非常有益。
201pub trait BufferWriter {
202    fn write<T>(&mut self, value: T::ValueType) -> &mut Self
203    where
204        T: Field<Self> + FieldWriter<Self>,
205    {
206        T::write(self, value);
207        self
208    }
209    fn revert<T>(&mut self) -> &mut Self
210    where
211        T: Field<Self> + FieldWriter<Self>,
212    {
213        T::revert(self);
214        self
215    }
216}
217/// # Buffer 读出器
218///
219/// 通常将 bit 字段归属的结构体看作缓存。通过实现 BufferReader 来对 bit 字段进行读出操作。
220/// bit 字段所归属的结构体需要实现该接口(如果含有任何可读 bit 字段)。
221///
222/// 👍 将 bit 字段归属的结构体看作缓存,在实现寄存器读写操作时会非常有益。
223pub trait BufferReader {
224    fn read<T: Field<Self> + FieldReader<Self>>(&self) -> T::ValueType {
225        T::read(self)
226    }
227    fn output<T: Field<Self> + FieldReader<Self>>(&self, out: &mut T::ValueType) -> &Self {
228        *out = T::read(self);
229        self
230    }
231}
232
233/// # 标识一个 bit 字段
234///
235/// 类型参数 BufferType 一般为 bit 字段所归属的结构体类型,这样可以保持一致性。
236/// 也可以是其他结构体类型,这样多个结构体类型将拥有同一个字段,但彼此的位置和值类型可以互不相同。
237pub trait Field<BufferType>
238where
239    BufferType: ?Sized,
240{
241    type ValueType;
242}
243
244/// # bit 字段写入器
245///
246/// bit 字段的实际写入函数,类型参数 BufferType 一般为 bit 字段归属的结构体类型。
247pub trait FieldWriter<BufferType>: Field<BufferType>
248where
249    BufferType: ?Sized,
250{
251    fn write(buffer: &mut BufferType, value: Self::ValueType);
252    fn revert(buffer: &mut BufferType);
253}
254/// # bit 字段读出器
255///
256/// bit 字段的实际读出函数,类型参数 BufferType 一般为 bit 字段归属的结构体类型。
257pub trait FieldReader<BufferType>: Field<BufferType>
258where
259    BufferType: ?Sized,
260{
261    fn read(buffer: &BufferType) -> Self::ValueType;
262}