1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
use NonZero;
/// ## Derive MapEnum for enum
///
/// **note: keep variant value same as define order (0..variants_count) will get optimized runtime performance**,
///
/// For tagged enum must add 'discriminant' or 'discriminant(attr_for_discriminant_enum)' attribute to define additional discriminant enum
/// ```ignore
/// #[derive(MapEnum)]
/// #[discriminant(derive(Clone, Copy))]
/// enum Enum1 {
/// Arm1(u8),
/// Arm2
/// }
/// ```
/// will generate discriminant enum additionally:
/// ```ignore
/// #[derive(Clone, Copy)]
/// enum Enum1Discriminant {
/// Arm1,
/// Arm2
/// }
/// ```
/// Map enum to `EnumMap`, macro version for `EnumMap::map_new`, can move value, can invoke in const, requires import `EnumMap` and `MapEnum`
///
/// ```ignore
/// #[derive(MapEnum)]
/// enum Enum1 {
/// Var0,
/// Var1,
/// }
///
/// const ENUM1: EnumMap<Enum1, u8> = map_enum!(match Enum1 {
/// Var0 => 2,
/// Var1 => 5,
/// });
///
/// #[derive(MapEnum)]
/// enum Enum2 {
/// Kar0,
/// Kar1,
/// }
///
/// /// support map multi level enum using tuple,
/// const ENUM2: EnumMap<Enum1, EnumMap<Enum2, u8>> = map_enum!(match (Enum1, Enum2) {
/// (Var0, Kar0) => 2,
/// (Var0, Kar1) => 5,
/// (Var1, Kar0) => 8,
/// (Var1, Kar1) => 9,
/// });
/// ```
/// Derive `IterEnumDiscriminants` for enum, providing compile-time iteration over
/// all discriminant names and their associated integer values.
///
/// This generates a constant iterator that can be used with `ecore::EnumDiscriminantsIterator`
/// to iterate over all variants and their associated metadata at runtime.
/// ## Derive BitsCast (for enum only right now)
///
/// Inside usage but not recommanded:
/// ```ignore
/// #[derive(BitsCast, Clone, Copy)] // must derive `Clone` and `Copy` too
/// #[bitfld(u8)] // must has helper attribute
/// enum {...}
/// ```
/// Recommand usage:
/// ```ignore
/// #[bitfld(u8)] // attribute macro `bitfld` will auto expand to correct usage
/// enum {...}
/// ```
/// ## Define bit field struct or bit field enum or bit field
///
/// ### Define bit enum
/// mark a enum can be used inside bit struct, if enum defined every value valid for repr type then impl `BitsCast`, otherwise impl `Uncheckable`
/// , derive [Clone] and [Copy] implicitly, default `#[repr(primary int of bits type)]` if not add `#[repr(..)]` attribute
/// ```ignore
/// #[bitfld(u3)] // u3 is bits type, actually expand to `#[derive(BitsCast, Clone, Copy)] #[bitfld(u3)] #[repr(u8)]`
/// #[derive(MapEnum)] // if requires `EnumMap<BitEnum1, ..>`
/// enum BitEnum1 {
/// A = 0,
/// B = 1
/// }
/// ```
/// For fieldness enum, must set `tag(ty, range)` and maybe set `payload(ty, range)` to define bits layout, `range` can be singlebit (like 2) or
/// bit range (like 1..3 or 1..=2) or start:bits (like 1:2). `range` is optional, if omited in `tag` then default is start from zero,
/// if omited in `payload` then default is start from tag end until total end. `tag` type `ty` must be int type but `payload` type `ty` must be unsigned int type
/// ```ignore
/// #[bitfld(u4, tag(u1, 0), payload(u3, 1..4))]
/// #[derive(MapEnum)] // if requires `EnumMap<BitEnum1, ..>`
/// enum BitEnum2 {
/// A(u2) = 0,
/// B(u3) = 1
/// }
/// ```
/// ### Define bit field struct, note:
/// * ****Every field in struct will be convert to a method to get bit field ref****
/// * because fields will be convert to method, `#[bitfld(...)]` maybe needs to add before other attributes if it requires real field
/// * underlying type must be unsigned basic int (u1, u2, ..., u128)
/// * bit field type can be any `T: BitsCast` type and `[T; N]` array and `EnumMap<Enum, T> where Enum: MapEnum`,
/// includes u1, u2, ..., u128, i1, i2, ..., i128, bool, any bit struct and any bit enum
/// * derive [Clone] and [Copy] and `bytemuck::Zeroable` and [`BitsCast`], derive `bytemuck::Pod` and `ConvertEndian` or `Uncheckable` only if avaiable
/// * default `#[repr(transparent)]` if not add `#[repr(..)]` attribute
/// ```ignore
/// #[bitfld(pub u32, relative)] // using #[bitfld(pub u32, .., overlay, ..)] will allow overlay for all fields, u32 is underlying type
/// struct BitStruct1 {
/// pub a: bitfld!(bool, 1), // single bit, same as 1..2 or 1..=1 or 1:1
///
/// pub b: bitfld!(BitEnum1, 2..=4), // same as 2..5 or 2:3
///
/// pub c: bitfld!(u5, 2..7, overlay), // same as 2..=6 or 2:5, reuqires `overlay` here because overlay field `b`
///
/// pub d: bitfld!(i3, :3), // occupy 3 bits, start bit use next bit of pre defined bit field, same as 7..10 or 7..=9 or 7:3 here
///
/// pub e: bitfld!(bool, ..11), // start bit use next bit of pre defined bit field, same as 10..11 or 10..=10 or 10:1 here
///
/// pub f: bitfld!([u2; 2], 11:4) // same as 11..15 or 11..=14 here, array of any `BitsCast` type is allowed
///
/// pub g: bitfld!(EnumMap<BitEnum1, u4>, 15:4) // same as 15..19 or 15..=18 here, enum map of any `BitsCast` type is allowed
///
/// #[bitfld(19..=22)] // same as ..=22 or 19..23 or ..23 or 19:4 or :4, syntax same as bitfld!(..) without the first bit type
/// pub h: EnumMap<BitEnum1, u4>, // using attribute to define bit field is also ok
///
/// pub i: bitfld!(u9, ..), // from next bit of pre defined bit field, until end of underlying, same as 23..32 or 23..=31 or 23:9 here
/// }
/// ```
/// ### Define bit field
/// using attribute `#[bitfld(range, attributes..)]` or macro type `bitfld!(bittype, range, attributes..)` to define bit field
/// * absolute range `a..b` or `a..=b` or single bit `a`(= `a..a+1` or `a..=a`) or `a:bits`(= `a..a+bits`)
/// * relative range, start from next bit of pre defined bit field, `..b` or `..=b` or `:bits`, requires `relative` in bit struct's #[bitfld(..)]
/// * relative tail range, `a..` or `..`, occupy until underlying end, requires `relative` in bit struct's #[bitfld(..)]
/// Generate `RInt` type from value range, auto select `RRxx` value type
/// * full form `rint!(MIN..=MAX, default = DEFAULT, step = STEP, bits = BITS)`, `MIN` and `MAX` is required, others is optional
/// * range `MIN..=MAX` is same as `MIN..MAX+1``
/// * if `default` not setted, then is `MIN`
/// * if `step` not setted, then is 1, `step` must >= 1, and must ensure `MIN % STEP == 0 && MAX % STEP == 0 && DEFAULT % STEP == 0`
/// * if `bits` not setted, then is `((MAX - MIN) / STEP).bit_width()`
/// ```ignore
/// rint!(-10..=100) // RInt<u7, RRI8<-10, 100>>
/// rint!(-10..=100, default = 3) // RInt<u7, RRI8<-10, 100, 3>>
/// rint!(-10..=100, default = 20, step = 10) // RInt<u4, RRI8<-10, 100, 20, 10>>
/// rint!(3..50, default = 20) // RInt<u6, RRU8<3, 49, 20>>
/// rint!(3..50, default = 20, bits = 6) // RInt<u7, RRU8<3, 49, 20>>
/// ```
/// must 1~128
/// u1~u128
/// u1~u128 or i1~i128