use core::fmt;
use core::hash;
mod sealed {
pub trait Sealed {}
}
pub trait Pointer: Sized + Copy + hash::Hash + Eq + fmt::Debug + self::sealed::Sealed {
#[doc(hidden)]
unsafe fn new_unchecked(value: usize) -> Self;
fn new(value: usize) -> Option<Self>;
fn get(self) -> usize;
}
pub trait Width: self::sealed::Sealed {
#[doc(hidden)]
const EMPTY: Self;
type Pointer: Pointer;
}
macro_rules! implement {
($ty:ident, $non_zero:ident, $e:ident) => {
impl Width for $ty {
const EMPTY: Self = 0;
type Pointer = $e;
}
use core::num::$non_zero;
impl self::sealed::Sealed for $ty {}
impl self::sealed::Sealed for $e {}
#[doc = concat!(" [`Pointer`] implementation for `", stringify!($ty), "`.")]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
#[repr(transparent)]
pub struct $e($non_zero);
impl $e {
#[doc = concat!(" Safe constructor for the pointer.")]
#[doc = concat!(" Returns [`None`] if the value provided is out of bounds for the pointer type.")]
#[doc = concat!("use syntree::pointer::", stringify!($e), ";")]
#[doc = concat!(" let v = ", stringify!($e), "::new(0).ok_or(\"out of bounds\")?;")]
#[doc = concat!(" let v = ", stringify!($e), "::new(42).ok_or(\"out of bounds\")?;")]
#[inline]
pub fn new(value: usize) -> Option<Self> {
let value = <$ty>::try_from(value).ok()?;
$non_zero::new(value.wrapping_add(1)).map(Self)
}
#[doc = concat!(" Get the index of a pointer.")]
#[doc = concat!("use syntree::pointer::", stringify!($e), ";")]
#[doc = concat!(" let v = ", stringify!($e), "::new(0).ok_or(\"out of bounds\")?;")]
#[doc = concat!(" let v = ", stringify!($e), "::new(42).ok_or(\"out of bounds\")?;")]
#[inline]
pub fn get(self) -> usize {
self.0.get().wrapping_sub(1) as usize
}
}
#[doc = concat!(" Pointer used for `", stringify!($ty), "` type.")]
#[doc = concat!("use syntree::pointer::", stringify!($e), ";")]
#[doc = concat!(" let v = ", stringify!($e), "::new(0).ok_or(\"out of bounds\")?;")]
#[doc = concat!(" let v = ", stringify!($e), "::new(42).ok_or(\"out of bounds\")?;")]
impl crate::pointer::Pointer for $e {
#[inline]
unsafe fn new_unchecked(value: usize) -> Self {
let value = value as $ty;
Self($non_zero::new_unchecked(value.wrapping_add(1)))
}
#[inline]
fn new(value: usize) -> Option<Self> {
$e::new(value)
}
#[inline]
fn get(self) -> usize {
$e::get(self)
}
}
#[doc = concat!("use syntree::pointer::", stringify!($e), ";")]
#[doc = concat!(" let v = ", stringify!($e), "::default();")]
impl Default for $e {
#[inline]
fn default() -> Self {
unsafe { Self($non_zero::new_unchecked(1)) }
}
}
impl fmt::Debug for $e {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
self.get().fmt(f)
}
}
};
}
implement!(usize, NonZeroUsize, PointerUsize);
implement!(u8, NonZeroU8, PointerU8);
implement!(u16, NonZeroU16, PointerU16);
implement!(u32, NonZeroU32, PointerU32);
implement!(u64, NonZeroU64, PointerU64);
implement!(u128, NonZeroU128, PointerU128);