cfgrammar/idxnewtype.rs
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
// This macro generates a struct which exposes a u32 API (but which may, internally, use a smaller
// storage size).
use std::mem::size_of;
use num_traits::{PrimInt, Unsigned};
#[cfg(feature = "serde")]
use serde::{Deserialize, Serialize};
macro_rules! IdxNewtype {
($(#[$attr:meta])* $n: ident) => {
$(#[$attr])*
#[derive(Clone, Copy, Debug, Eq, Hash, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature="serde", derive(Serialize, Deserialize))]
pub struct $n<T>(pub T);
impl<T: PrimInt + Unsigned> From<$n<T>> for usize {
fn from($n(st): $n<T>) -> Self {
debug_assert!(size_of::<usize>() >= size_of::<T>());
num_traits::cast(st).unwrap()
}
}
impl<T: PrimInt + Unsigned> From<$n<T>> for u32 {
fn from($n(st): $n<T>) -> Self {
debug_assert!(size_of::<u32>() >= size_of::<T>());
num_traits::cast(st).unwrap()
}
}
impl<T: PrimInt + Unsigned> $n<T> {
pub fn as_storaget(&self) -> T {
let $n(st) = self;
*st
}
}
}
}
IdxNewtype!(
/// A type specifically for rule indices.
///
/// It is guaranteed that `RIdx` can be converted, without loss of precision, to `usize` with
/// the idiom `usize::from(...)`.
RIdx
);
IdxNewtype!(
/// A type specifically for production indices (e.g. a rule `E::=A|B` would
/// have two productions for the single rule `E`).
///
/// It is guaranteed that `PIdx` can be converted, without loss of precision, to `usize` with
/// the idiom `usize::from(...)`.
PIdx
);
IdxNewtype!(
/// A type specifically for symbol indices (within a production).
///
/// It is guaranteed that `SIdx` can be converted, without loss of precision, to `usize` with
/// the idiom `usize::from(...)`.
SIdx
);
IdxNewtype!(
/// A type specifically for token indices.
///
/// It is guaranteed that `TIdx` can be converted, without loss of precision, to `usize` with
/// the idiom `usize::from(...)`.
TIdx
);