use std::fmt::Debug;
use std::hash::Hash;
use error::{Error, Result};
pub fn premultiply_overflow_error<S: StateID>(
last_state: S,
alphabet_len: usize,
) -> Result<()> {
let requested = match last_state.to_usize().checked_mul(alphabet_len) {
Some(requested) => requested,
None => return Err(Error::premultiply_overflow(0, 0)),
};
if requested > S::max_id() {
return Err(Error::premultiply_overflow(S::max_id(), requested));
}
Ok(())
}
pub fn usize_to_state_id<S: StateID>(value: usize) -> Result<S> {
if value > S::max_id() {
Err(Error::state_id_overflow(S::max_id()))
} else {
Ok(S::from_usize(value))
}
}
pub fn fail_id<S: StateID>() -> S {
S::from_usize(0)
}
pub fn dead_id<S: StateID>() -> S {
S::from_usize(1)
}
mod private {
pub trait Sealed {}
impl Sealed for u8 {}
impl Sealed for u16 {}
impl Sealed for u32 {}
impl Sealed for u64 {}
impl Sealed for usize {}
}
pub unsafe trait StateID:
private::Sealed
+ Clone
+ Copy
+ Debug
+ Eq
+ Hash
+ PartialEq
+ PartialOrd
+ Ord
{
fn from_usize(n: usize) -> Self;
fn to_usize(self) -> usize;
fn max_id() -> usize;
}
unsafe impl StateID for usize {
#[inline]
fn from_usize(n: usize) -> usize {
n
}
#[inline]
fn to_usize(self) -> usize {
self
}
#[inline]
fn max_id() -> usize {
::std::usize::MAX
}
}
unsafe impl StateID for u8 {
#[inline]
fn from_usize(n: usize) -> u8 {
n as u8
}
#[inline]
fn to_usize(self) -> usize {
self as usize
}
#[inline]
fn max_id() -> usize {
::std::u8::MAX as usize
}
}
unsafe impl StateID for u16 {
#[inline]
fn from_usize(n: usize) -> u16 {
n as u16
}
#[inline]
fn to_usize(self) -> usize {
self as usize
}
#[inline]
fn max_id() -> usize {
::std::u16::MAX as usize
}
}
#[cfg(any(target_pointer_width = "32", target_pointer_width = "64"))]
unsafe impl StateID for u32 {
#[inline]
fn from_usize(n: usize) -> u32 {
n as u32
}
#[inline]
fn to_usize(self) -> usize {
self as usize
}
#[inline]
fn max_id() -> usize {
::std::u32::MAX as usize
}
}
#[cfg(target_pointer_width = "64")]
unsafe impl StateID for u64 {
#[inline]
fn from_usize(n: usize) -> u64 {
n as u64
}
#[inline]
fn to_usize(self) -> usize {
self as usize
}
#[inline]
fn max_id() -> usize {
::std::u64::MAX as usize
}
}