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
use std::fmt::Debug; pub struct CastFailure<T, U: Debug> { value: U, _marker: std::marker::PhantomData<T>, } impl<T, U: Debug> Debug for CastFailure<T, U> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { f.debug_struct("CastFailure") .field("value", &self.value) .finish() } } impl<T, U: Debug> From<U> for CastFailure<T, U> { fn from(value: U) -> Self { Self { value, _marker: std::marker::PhantomData, } } } impl<T, U: Debug> std::fmt::Display for CastFailure<T, U> { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!( f, "cast failed: value {:?} of type `{}` could not be represented by type `{}`", self.value, std::any::type_name::<U>(), std::any::type_name::<T>(), ) } } impl<T, U: Debug> std::error::Error for CastFailure<T, U> {} impl<T, U: Debug> CastFailure<T, U> { #[cold] fn panic(self) -> ! { panic!("{}", self); } } pub fn try_cast<T: num_traits::NumCast, U: Copy + Debug + num_traits::ToPrimitive>( n: U, ) -> Result<T, CastFailure<T, U>> { T::from(n).ok_or_else(move || n.into()) } pub fn cast<T: num_traits::NumCast, U: Copy + Debug + num_traits::ToPrimitive>(n: U) -> T { try_cast(n).unwrap_or_else(move |err| err.panic()) }