use core::fmt::Debug;
use core::hash::Hash;
use core::mem::size_of;
use byteorder::{ByteOrder, NativeEndian};
#[cfg(feature = "std")]
pub use self::std::*;
#[cfg(feature = "std")]
mod std {
use core::mem::size_of;
use byteorder::ByteOrder;
use error::{Error, Result};
use super::StateID;
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 next_state_id<S: StateID>(current: S) -> Result<S> {
let next = match current.to_usize().checked_add(1) {
Some(next) => next,
None => return Err(Error::state_id_overflow(::std::usize::MAX)),
};
if next > S::max_id() {
return Err(Error::state_id_overflow(S::max_id()));
}
Ok(S::from_usize(next))
}
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 write_state_id_bytes<E: ByteOrder, S: StateID>(
slice: &mut [u8],
id: S,
) {
assert!(
1 == size_of::<S>()
|| 2 == size_of::<S>()
|| 4 == size_of::<S>()
|| 8 == size_of::<S>()
);
match size_of::<S>() {
1 => slice[0] = id.to_usize() as u8,
2 => E::write_u16(slice, id.to_usize() as u16),
4 => E::write_u32(slice, id.to_usize() as u32),
8 => E::write_u64(slice, id.to_usize() as u64),
_ => unreachable!(),
}
}
}
pub fn dead_id<S: StateID>() -> S {
S::from_usize(0)
}
pub unsafe trait StateID:
Clone + Copy + Debug + Eq + Hash + PartialEq + PartialOrd + Ord
{
fn from_usize(n: usize) -> Self;
fn to_usize(self) -> usize;
fn max_id() -> usize;
fn read_bytes(slice: &[u8]) -> Self;
fn write_bytes(self, slice: &mut [u8]);
}
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 { ::core::usize::MAX }
#[inline]
fn read_bytes(slice: &[u8]) -> Self {
NativeEndian::read_uint(slice, size_of::<usize>()) as usize
}
#[inline]
fn write_bytes(self, slice: &mut [u8]) {
NativeEndian::write_uint(slice, self as u64, size_of::<usize>())
}
}
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 { ::core::u8::MAX as usize }
#[inline]
fn read_bytes(slice: &[u8]) -> Self {
slice[0]
}
#[inline]
fn write_bytes(self, slice: &mut [u8]) {
slice[0] = self;
}
}
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 { ::core::u16::MAX as usize }
#[inline]
fn read_bytes(slice: &[u8]) -> Self {
NativeEndian::read_u16(slice)
}
#[inline]
fn write_bytes(self, slice: &mut [u8]) {
NativeEndian::write_u16(slice, self)
}
}
#[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 { ::core::u32::MAX as usize }
#[inline]
fn read_bytes(slice: &[u8]) -> Self {
NativeEndian::read_u32(slice)
}
#[inline]
fn write_bytes(self, slice: &mut [u8]) {
NativeEndian::write_u32(slice, self)
}
}
#[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 { ::core::u64::MAX as usize }
#[inline]
fn read_bytes(slice: &[u8]) -> Self {
NativeEndian::read_u64(slice)
}
#[inline]
fn write_bytes(self, slice: &mut [u8]) {
NativeEndian::write_u64(slice, self)
}
}