58 lines
1.2 KiB
Rust
58 lines
1.2 KiB
Rust
pub trait Narrow{
|
|
type Output;
|
|
fn narrow(self)->Self::Output;
|
|
}
|
|
#[derive(Debug)]
|
|
pub enum Error{
|
|
Overflow,
|
|
Underflow,
|
|
}
|
|
impl std::fmt::Display for Error{
|
|
fn fmt(&self,f:&mut std::fmt::Formatter<'_>)->std::fmt::Result{
|
|
write!(f,"{self:?}")
|
|
}
|
|
}
|
|
impl std::error::Error for Error{}
|
|
pub trait TryNarrow{
|
|
type Output;
|
|
fn try_narrow(self)->Result<Self::Output,Error>;
|
|
}
|
|
#[cfg(test)]
|
|
mod tests {
|
|
use super::*;
|
|
|
|
//TODO: use num_traits to do a blanket implementation (self<T::MIN as U)
|
|
impl TryNarrow for i16{
|
|
type Output=i8;
|
|
fn try_narrow(self)->Result<Self::Output,Error>{
|
|
if self<i8::MIN as i16{
|
|
return Err(Error::Underflow);
|
|
}
|
|
if (i8::MAX as i16)<self{
|
|
return Err(Error::Overflow);
|
|
}
|
|
Ok(self as i8)
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_i16_i8(){
|
|
assert!(matches!(257i16.try_narrow(),Err(Error::Overflow)));
|
|
assert!(matches!(64i16.try_narrow(),Ok(64i8)));
|
|
assert!(matches!((-257i16).try_narrow(),Err(Error::Underflow)));
|
|
}
|
|
|
|
impl Narrow for fixed::FixedI16<typenum::consts::U8>{
|
|
type Output=i8;
|
|
fn narrow(self)->Self::Output{
|
|
(self.to_bits()>>8) as i8
|
|
}
|
|
}
|
|
|
|
#[test]
|
|
fn test_fixed_i16_i8(){
|
|
let a=fixed::FixedI16::<typenum::consts::U8>::from(5)/2;
|
|
assert_eq!(a.narrow(),2);
|
|
}
|
|
}
|