cfgrammar/
idxnewtype.rs

1// This macro generates a struct which exposes a u32 API (but which may, internally, use a smaller
2// storage size).
3
4use std::mem::size_of;
5
6#[cfg(feature = "bincode")]
7use bincode::{Decode, Encode};
8use num_traits::{PrimInt, Unsigned};
9#[cfg(feature = "serde")]
10use serde::{Deserialize, Serialize};
11
12macro_rules! IdxNewtype {
13    ($(#[$attr:meta])* $n: ident) => {
14        $(#[$attr])*
15        #[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
16        #[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
17        #[cfg_attr(feature="bincode", derive(Encode, Decode))]
18        pub struct $n<T>(pub T);
19
20        impl<T: PrimInt + Unsigned> From<$n<T>> for usize {
21            fn from($n(st): $n<T>) -> Self {
22                debug_assert!(size_of::<usize>() >= size_of::<T>());
23                num_traits::cast(st).unwrap()
24            }
25        }
26
27        impl<T: PrimInt + Unsigned> From<$n<T>> for u32 {
28            fn from($n(st): $n<T>) -> Self {
29                debug_assert!(size_of::<u32>() >= size_of::<T>());
30                num_traits::cast(st).unwrap()
31            }
32        }
33
34        impl<T: PrimInt + Unsigned> $n<T> {
35            pub fn as_storaget(&self) -> T {
36                let $n(st) = self;
37                *st
38            }
39        }
40    }
41}
42
43IdxNewtype!(
44    /// A type specifically for rule indices.
45    ///
46    /// It is guaranteed that `RIdx` can be converted, without loss of precision, to `usize` with
47    /// the idiom `usize::from(...)`.
48    RIdx
49);
50IdxNewtype!(
51    /// A type specifically for production indices (e.g. a rule `E::=A|B` would
52    /// have two productions for the single rule `E`).
53    ///
54    /// It is guaranteed that `PIdx` can be converted, without loss of precision, to `usize` with
55    /// the idiom `usize::from(...)`.
56    PIdx
57);
58IdxNewtype!(
59    /// A type specifically for symbol indices (within a production).
60    ///
61    /// It is guaranteed that `SIdx` can be converted, without loss of precision, to `usize` with
62    /// the idiom `usize::from(...)`.
63    SIdx
64);
65IdxNewtype!(
66    /// A type specifically for token indices.
67    ///
68    /// It is guaranteed that `TIdx` can be converted, without loss of precision, to `usize` with
69    /// the idiom `usize::from(...)`.
70    TIdx
71);