1#[macro_export]
156macro_rules! define_index_type {
157 (
159 $(#[$attrs:meta])*
160 $v:vis struct $type:ident = $raw:ident;
161 $($CONFIG_NAME:ident = $value:expr;)* $(;)?
162 ) => {
163 $crate::__define_index_type_inner!{
164 @configs [$(($CONFIG_NAME; $value))*]
165 @attrs [$(#[$attrs])*]
166 @derives [#[derive(Copy, Clone, PartialEq, Eq, Hash, PartialOrd, Ord)]]
167 @decl [$v struct $type ($raw)]
168 @debug_fmt ["{}"]
169 @max [(<$raw>::max_value() as usize)]
170 @no_check_max [false]
171 }
172 };
173}
174
175#[macro_export]
176#[doc(hidden)]
177macro_rules! unknown_define_index_type_option {
178 () => {};
179}
180
181#[cfg(feature = "serde")]
182#[macro_export]
183#[doc(hidden)]
184macro_rules! __internal_maybe_index_impl_serde {
185 ($type:ident) => {
186 impl serde::ser::Serialize for $type {
187 fn serialize<S: serde::ser::Serializer>(
188 &self,
189 serializer: S,
190 ) -> Result<S::Ok, S::Error> {
191 self.index().serialize(serializer)
192 }
193 }
194
195 impl<'de> serde::de::Deserialize<'de> for $type {
196 fn deserialize<D: serde::de::Deserializer<'de>>(
197 deserializer: D,
198 ) -> Result<Self, D::Error> {
199 usize::deserialize(deserializer).map(Self::from_usize)
200 }
201 }
202 };
203}
204
205#[cfg(not(feature = "serde"))]
206#[macro_export]
207#[doc(hidden)]
208macro_rules! __internal_maybe_index_impl_serde {
209 ($type:ident) => {};
210}
211
212#[cfg(feature = "rkyv")]
213#[macro_export]
214#[doc(hidden)]
215macro_rules! __internal_maybe_index_impl_rkyv {
216 ($type:ident) => {
217 impl rkyv::Archive for $type {
218 type Archived = <usize as rkyv::Archive>::Archived;
219 type Resolver = <usize as rkyv::Archive>::Resolver;
220
221 #[inline]
222 unsafe fn resolve(
223 &self,
224 pos: usize,
225 resolver: Self::Resolver,
226 out: *mut Self::Archived,
227 ) {
228 self.index().resolve(pos, resolver, out)
229 }
230 }
231
232 impl<S: rkyv::ser::ScratchSpace + rkyv::ser::Serializer + ?Sized> rkyv::Serialize<S>
233 for $type
234 {
235 #[inline]
236 fn serialize(
237 &self,
238 serializer: &mut S,
239 ) -> Result<Self::Resolver, <S as rkyv::Fallible>::Error> {
240 self.index().serialize(serializer)
241 }
242 }
243
244 impl<D: rkyv::Fallible + ?Sized> rkyv::Deserialize<$type, D>
245 for rkyv::Archived<rkyv::FixedUsize>
246 {
247 #[inline]
248 fn deserialize(&self, deserializer: &mut D) -> Result<$type, D::Error> {
249 let index = rkyv::Archived::<rkyv::FixedUsize>::deserialize(self, deserializer)?;
250
251 Ok($type::from_usize(index))
252 }
253 }
254 };
255}
256
257#[cfg(not(feature = "rkyv"))]
258#[macro_export]
259#[doc(hidden)]
260macro_rules! __internal_maybe_index_impl_rkyv {
261 ($type:ident) => {};
262}
263
264#[macro_export]
265#[doc(hidden)]
266macro_rules! __define_index_type_inner {
267 (
269 @configs [(DISABLE_MAX_INDEX_CHECK; $no_check_max:expr) $(($CONFIG_NAME:ident; $value:expr))*]
270 @attrs [$(#[$attrs:meta])*]
271 @derives [$(#[$derive:meta])*]
272 @decl [$v:vis struct $type:ident ($raw:ident)]
273 @debug_fmt [$dbg:expr]
274 @max [$max:expr]
275 @no_check_max [$_old_no_check_max:expr]
276 ) => {
277 $crate::__define_index_type_inner!{
278 @configs [$(($CONFIG_NAME; $value))*]
279 @attrs [$(#[$attrs])*]
280 @derives [$(#[$derive])*]
281 @decl [$v struct $type ($raw)]
282 @debug_fmt [$dbg]
283 @max [$max]
284 @no_check_max [$no_check_max]
285 }
286 };
287
288 (
290 @configs [(MAX_INDEX; $new_max:expr) $(($CONFIG_NAME:ident; $value:expr))*]
291 @attrs [$(#[$attrs:meta])*]
292 @derives [$(#[$derive:meta])*]
293 @decl [$v:vis struct $type:ident ($raw:ident)]
294 @debug_fmt [$dbg:expr]
295 @max [$max:expr]
296 @no_check_max [$cm:expr]
297 ) => {
298 $crate::__define_index_type_inner!{
299 @configs [$(($CONFIG_NAME; $value))*]
300 @attrs [$(#[$attrs])*]
301 @derives [$(#[$derive])*]
302 @decl [$v struct $type ($raw)]
303 @debug_fmt [$dbg]
304 @max [$new_max]
305 @no_check_max [$cm]
306 }
307 };
308
309 (
311 @configs [(DEFAULT; $default_expr:expr) $(($CONFIG_NAME:ident; $value:expr))*]
312 @attrs [$(#[$attrs:meta])*]
313 @derives [$(#[$derive:meta])*]
314 @decl [$v:vis struct $type:ident ($raw:ident)]
315 @debug_fmt [$dbg:expr]
316 @max [$max:expr]
317 @no_check_max [$no_check_max:expr]
318 ) => {
319 $crate::__define_index_type_inner!{
320 @configs [$(($CONFIG_NAME; $value))*]
321 @attrs [$(#[$attrs])*]
322 @derives [$(#[$derive])*]
323 @decl [$v struct $type ($raw)]
324 @debug_fmt [$dbg]
325 @max [$max]
326 @no_check_max [$no_check_max]
327 }
328 impl Default for $type {
329 #[inline]
330 fn default() -> Self {
331 $default_expr
332 }
333 }
334 };
335
336 (
338 @configs [(DEBUG_FORMAT; $dbg:expr) $(($CONFIG_NAME:ident; $value:expr))*]
339 @attrs [$(#[$attrs:meta])*]
340 @derives [$(#[$derive:meta])*]
341 @decl [$v:vis struct $type:ident ($raw:ident)]
342 @debug_fmt [$old_dbg:expr]
343 @max [$max:expr]
344 @no_check_max [$no_check_max:expr]
345 ) => {
346 $crate::__define_index_type_inner!{
347 @configs [$(($CONFIG_NAME; $value))*]
348 @attrs [$(#[$attrs])*]
349 @derives [$(#[$derive])*]
350 @decl [$v struct $type ($raw)]
351 @debug_fmt [$dbg]
352 @max [$max]
353 @no_check_max [$no_check_max]
354 }
355 };
356
357 (
359 @configs [(DISPLAY_FORMAT; $format:expr) $(($CONFIG_NAME:ident; $value:expr))*]
360 @attrs [$(#[$attrs:meta])*]
361 @derives [$(#[$derive:meta])*]
362 @decl [$v:vis struct $type:ident ($raw:ident)]
363 @debug_fmt [$dbg:expr]
364 @max [$max:expr]
365 @no_check_max [$no_check_max:expr]
366 ) => {
367 $crate::__define_index_type_inner!{
368 @configs [$(($CONFIG_NAME; $value))*]
369 @attrs [$(#[$attrs])*]
370 @derives [$(#[$derive])*]
371 @decl [$v struct $type ($raw)]
372 @debug_fmt [$dbg]
373 @max [$max]
374 @no_check_max [$no_check_max]
375 }
376
377 impl core::fmt::Display for $type {
378 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
379 write!(f, $format, self.index())
380 }
381 }
382 };
383
384 (
386 @configs [(IMPL_RAW_CONVERSIONS; $val:expr) $(($CONFIG_NAME:ident; $value:expr))*]
387 @attrs [$(#[$attrs:meta])*]
388 @derives [$(#[$derive:meta])*]
389 @decl [$v:vis struct $type:ident ($raw:ident)]
390 @debug_fmt [$dbg:expr]
391 @max [$max:expr]
392 @no_check_max [$no_check_max:expr]
393 ) => {
394 $crate::__define_index_type_inner!{
395 @configs [$(($CONFIG_NAME; $value))*]
396 @attrs [$(#[$attrs])*]
397 @derives [$(#[$derive])*]
398 @decl [$v struct $type ($raw)]
399 @debug_fmt [$dbg]
400 @max [$max]
401 @no_check_max [$no_check_max]
402 }
403 const _: [(); 1] = [(); $val as usize];
405
406 impl From<$type> for $raw {
407 #[inline]
408 fn from(v: $type) -> $raw {
409 v.raw()
410 }
411 }
412
413 impl From<$raw> for $type {
414 #[inline]
415 fn from(value: $raw) -> Self {
416 Self::from_raw(value)
417 }
418 }
419 };
420 (
422 @configs [($other:ident; $format:expr) $(($CONFIG_NAME:ident; $value:expr))*]
423 @attrs [$(#[$attrs:meta])*]
424 @derives [$(#[$derive:meta])*]
425 @decl [$v:vis struct $type:ident ($raw:ident)]
426 @debug_fmt [$dbg:expr]
427 @max [$max:expr]
428 @no_check_max [$no_check_max:expr]
429 ) => {
430 $crate::unknown_define_index_type_option!($other);
431 };
432 (
434 @configs []
435 @attrs [$(#[$attrs:meta])*]
436 @derives [$(#[$derive:meta])*]
437 @decl [$v:vis struct $type:ident ($raw:ident)]
438 @debug_fmt [$dbg:expr]
439 @max [$max:expr]
440 @no_check_max [$no_check_max:expr]
441 ) => {
442
443 $(#[$derive])*
444 $(#[$attrs])*
445 #[repr(transparent)]
446 $v struct $type { _raw: $raw }
447
448 impl $type {
449 $v const MAX_INDEX: usize = $max;
453
454 $v const CHECKS_MAX_INDEX: bool = !$no_check_max;
457
458 #[inline(always)]
460 $v fn new(value: usize) -> Self {
461 Self::from_usize(value)
462 }
463
464 #[inline(always)]
466 $v fn from_raw(value: $raw) -> Self {
467 Self::from_usize(value as usize)
468 }
469
470 #[inline(always)]
472 $v fn from_foreign<F: $crate::Idx>(value: F) -> Self {
473 Self::from_usize(value.index())
474 }
475
476 #[inline(always)]
478 $v const fn from_usize_unchecked(value: usize) -> Self {
479 Self { _raw: value as $raw }
480 }
481
482 #[inline(always)]
484 $v const fn from_raw_unchecked(raw: $raw) -> Self {
485 Self { _raw: raw }
486 }
487
488 #[inline]
490 $v fn from_usize(value: usize) -> Self {
491 Self::check_index(value as usize);
492 Self { _raw: value as $raw }
493 }
494
495 #[inline(always)]
497 $v const fn index(self) -> usize {
498 self._raw as usize
499 }
500
501 #[inline(always)]
503 $v const fn raw(self) -> $raw {
504 self._raw
505 }
506
507 #[inline]
509 $v fn check_index(v: usize) {
510 if Self::CHECKS_MAX_INDEX && (v > Self::MAX_INDEX) {
511 $crate::__max_check_fail(v, Self::MAX_INDEX);
512 }
513 }
514
515 const _ENSURE_RAW_IS_UNSIGNED: [(); 0] = [(); <$raw>::MIN as usize];
516 }
517
518 impl core::fmt::Debug for $type {
519 fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
520 write!(f, $dbg, self.index())
521 }
522 }
523
524 impl core::cmp::PartialOrd<usize> for $type {
525 #[inline]
526 fn partial_cmp(&self, other: &usize) -> Option<core::cmp::Ordering> {
527 self.index().partial_cmp(other)
528 }
529 }
530
531 impl core::cmp::PartialOrd<$type> for usize {
532 #[inline]
533 fn partial_cmp(&self, other: &$type) -> Option<core::cmp::Ordering> {
534 self.partial_cmp(&other.index())
535 }
536 }
537
538 impl PartialEq<usize> for $type {
539 #[inline]
540 fn eq(&self, other: &usize) -> bool {
541 self.index() == *other
542 }
543 }
544
545 impl PartialEq<$type> for usize {
546 #[inline]
547 fn eq(&self, other: &$type) -> bool {
548 *self == other.index()
549 }
550 }
551
552 impl core::ops::Add<usize> for $type {
553 type Output = Self;
554 #[inline]
555 fn add(self, other: usize) -> Self {
556 Self::new(self.index().wrapping_add(other))
560 }
561 }
562
563 impl core::ops::Sub<usize> for $type {
564 type Output = Self;
565 #[inline]
566 fn sub(self, other: usize) -> Self {
567 Self::new(self.index().wrapping_sub(other))
571 }
572 }
573
574 impl core::ops::AddAssign<usize> for $type {
575 #[inline]
576 fn add_assign(&mut self, other: usize) {
577 *self = *self + other
578 }
579 }
580
581 impl core::ops::SubAssign<usize> for $type {
582 #[inline]
583 fn sub_assign(&mut self, other: usize) {
584 *self = *self - other;
585 }
586 }
587
588 impl core::ops::Rem<usize> for $type {
589 type Output = Self;
590 #[inline]
591 fn rem(self, other: usize) -> Self {
592 Self::new(self.index() % other)
593 }
594 }
595
596 impl core::ops::Add<$type> for usize {
597 type Output = $type;
598 #[inline]
599 fn add(self, other: $type) -> $type {
600 other + self
601 }
602 }
603
604 impl core::ops::Sub<$type> for usize {
605 type Output = $type;
606 #[inline]
607 fn sub(self, other: $type) -> $type {
608 $type::new(self.wrapping_sub(other.index()))
609 }
610 }
611
612 impl core::ops::Add for $type {
613 type Output = $type;
614 #[inline]
615 fn add(self, other: $type) -> $type {
616 $type::new(other.index() + self.index())
617 }
618 }
619
620 impl core::ops::Sub for $type {
621 type Output = $type;
622 #[inline]
623 fn sub(self, other: $type) -> $type {
624 $type::new(self.index().wrapping_sub(other.index()))
625 }
626 }
627
628 impl core::ops::AddAssign for $type {
629 #[inline]
630 fn add_assign(&mut self, other: $type) {
631 *self = *self + other
632 }
633 }
634
635 impl core::ops::SubAssign for $type {
636 #[inline]
637 fn sub_assign(&mut self, other: $type) {
638 *self = *self - other;
639 }
640 }
641
642 impl $crate::Idx for $type {
643 #[inline]
644 fn from_usize(value: usize) -> Self {
645 Self::from(value)
646 }
647
648 #[inline]
649 fn index(self) -> usize {
650 usize::from(self)
651 }
652 }
653
654 impl From<$type> for usize {
655 #[inline]
656 fn from(v: $type) -> usize {
657 v.index()
658 }
659 }
660
661 impl From<usize> for $type {
662 #[inline]
663 fn from(value: usize) -> Self {
664 $type::from_usize(value)
665 }
666 }
667
668 $crate::__internal_maybe_index_impl_serde!($type);
669 $crate::__internal_maybe_index_impl_rkyv!($type);
670 };
671}