1pub trait Idx: Sized + Copy + 'static {
4 fn new(idx: usize) -> Self;
5
6 fn index(self) -> usize;
7
8 fn inc_one(&mut self) -> Self {
9 let old = *self;
10 *self = self.plus(1);
11 old
12 }
13
14 fn increment_by(&mut self, amount: usize) {
15 *self = self.plus(amount);
16 }
17
18 fn plus(self, amount: usize) -> Self {
19 Self::new(self.index() + amount)
20 }
21}
22
23#[macro_export]
24macro_rules! newtype_index {
25 ($(#[$attrs:meta])* $v:vis struct $name:ident { .. }) => (
29 $crate::newtype_index!(
30 @attrs [$(#[$attrs])*]
32 @type [$name]
33 @max [0xFFFF_FF00]
35 @vis [$v]
36 @debug_format ["{}"]);
37 );
38
39 ($(#[$attrs:meta])* $v:vis struct $name:ident { $($tokens:tt)+ }) => (
41 $crate::newtype_index!(
42 @attrs [$(#[$attrs])*]
44 @type [$name]
45 @max [0xFFFF_FF00]
47 @vis [$v]
48 @debug_format ["{}"]
49 $($tokens)+);
50 );
51
52 (@derives [$($derives:ident,)*]
56 @attrs [$(#[$attrs:meta])*]
57 @type [$type:ident]
58 @max [$max:expr]
59 @vis [$v:vis]
60 @debug_format [$debug_format:tt]) => (
61 $(#[$attrs])*
62 #[derive(Copy, PartialEq, Eq, Hash, PartialOrd, Ord, $($derives),*)]
63 $v struct $type {
64 private: u32
65 }
66
67 impl Clone for $type {
68 #[inline]
69 fn clone(&self) -> Self {
70 *self
71 }
72 }
73
74 impl $type {
75 $v const MAX_AS_U32: u32 = $max;
77
78 $v const MAX: Self = Self::from_u32($max);
80
81 #[inline]
87 $v const fn from_usize(value: usize) -> Self {
88 assert!(value <= ($max as usize));
89 unsafe {
91 Self::from_u32_unchecked(value as u32)
92 }
93 }
94
95 #[inline]
101 $v const fn from_u32(value: u32) -> Self {
102 assert!(value <= $max);
103 unsafe {
105 Self::from_u32_unchecked(value)
106 }
107 }
108
109 #[inline]
118 $v const unsafe fn from_u32_unchecked(value: u32) -> Self {
119 Self { private: value }
120 }
121
122 #[inline]
124 $v const fn index(self) -> usize {
125 self.as_usize()
126 }
127
128 #[inline]
130 $v const fn as_u32(self) -> u32 {
131 self.private
132 }
133
134 #[inline]
136 $v const fn as_usize(self) -> usize {
137 self.as_u32() as usize
138 }
139 }
140
141 impl std::ops::Add<usize> for $type {
142 type Output = Self;
143
144 fn add(self, other: usize) -> Self {
145 Self::from_usize(self.index() + other)
146 }
147 }
148
149 impl $crate::index::Idx for $type {
150 #[inline]
151 fn new(value: usize) -> Self {
152 Self::from_usize(value)
153 }
154
155 #[inline]
156 fn index(self) -> usize {
157 self.as_usize()
158 }
159 }
160
161
162 impl From<$type> for u32 {
163 #[inline]
164 fn from(v: $type) -> u32 {
165 v.as_u32()
166 }
167 }
168
169 impl From<$type> for usize {
170 #[inline]
171 fn from(v: $type) -> usize {
172 v.as_usize()
173 }
174 }
175
176 impl From<usize> for $type {
177 #[inline]
178 fn from(value: usize) -> Self {
179 Self::from_usize(value)
180 }
181 }
182
183 impl From<u32> for $type {
184 #[inline]
185 fn from(value: u32) -> Self {
186 Self::from_u32(value)
187 }
188 }
189
190 $crate::newtype_index!(
191 @handle_debug
192 @derives [$($derives,)*]
193 @type [$type]
194 @debug_format [$debug_format]);
195 );
196
197 (@handle_debug
199 @derives [$($_derives:ident,)*]
200 @type [$type:ident]
201 @debug_format [custom]) => ();
202
203 (@handle_debug
205 @derives []
206 @type [$type:ident]
207 @debug_format [$debug_format:tt]) => (
208 impl ::std::fmt::Debug for $type {
209 fn fmt(&self, fmt: &mut ::std::fmt::Formatter<'_>) -> ::std::fmt::Result {
210 write!(fmt, $debug_format, self.as_u32())
211 }
212 }
213 );
214
215 (@handle_debug
217 @derives [$_derive:ident, $($derives:ident,)*]
218 @type [$type:ident]
219 @debug_format [$debug_format:tt]) => (
220 $crate::newtype_index!(
221 @handle_debug
222 @derives [$($derives,)*]
223 @type [$type]
224 @debug_format [$debug_format]);
225 );
226
227
228
229 (@attrs [$(#[$attrs:meta])*]
230 @type [$type:ident]
231 @max [$max:expr]
232 @vis [$v:vis]
233 @debug_format [$debug_format:tt]
234 $($tokens:tt)*) => (
235 $crate::newtype_index!(
236 @derives []
237 @attrs [$(#[$attrs])*]
238 @type [$type]
239 @max [$max]
240 @vis [$v]
241 @debug_format [$debug_format]
242 $($tokens)*);
243 );
244}
245
246impl Idx for usize {
247 fn new(idx: usize) -> Self {
248 idx
249 }
250
251 fn index(self) -> usize {
252 self
253 }
254}
255
256impl Idx for u32 {
257 fn new(idx: usize) -> Self {
258 idx as u32
259 }
260
261 fn index(self) -> usize {
262 self as usize
263 }
264}