diff --git a/src/lib.rs b/src/lib.rs index 2f9864b0..5ce0f523 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -273,7 +273,9 @@ pub mod num { #[cfg(not(feature = "std"))] pub use num_traits::float::FloatCore as Float; - pub use num_traits::{pow, FromPrimitive, Num, One, Saturating, Signed, ToPrimitive, Zero}; + pub use num_traits::{ + pow, AsPrimitive, FromPrimitive, Num, NumCast, One, Saturating, Signed, ToPrimitive, Zero, + }; #[cfg(feature = "bigint-support")] pub use num_bigint::{BigInt, BigUint}; diff --git a/src/system.rs b/src/system.rs index d73ff3c1..8499a0be 100644 --- a/src/system.rs +++ b/src/system.rs @@ -381,6 +381,72 @@ macro_rules! system { .value() }} + impl Quantity, V> + where + D: Dimension + ?Sized, + $units: Units, + V: $crate::num::Num + $crate::Conversion, + { + /// Cast to a quantity with the same dimension and unit but a different underlying + /// storage type allowing for narrowing and precision loss. + /// + /// # Examples + #[cfg_attr(all(feature = "si", feature = "f32", feature = "i32"), doc = " ```rust")] + #[cfg_attr(not(all(feature = "si", feature = "f32", feature = "i32")), doc = " ```rust,ignore")] + /// # use uom::si::{f32, i32}; + /// # use uom::si::time::second; + /// let t = f32::Time::new::(1.5); + /// + /// let t: i32::Time = t.as_(); + /// + /// assert_eq!(t.get::(), 1); + /// ``` + #[inline(always)] + pub fn as_(self) -> Quantity, W> + where + V: $crate::num::AsPrimitive, + $units: Units, + W: $crate::num::Num + $crate::Conversion + Copy + 'static, + { + Quantity { + dimension: $crate::lib::marker::PhantomData, + units: $crate::lib::marker::PhantomData, + value: self.value.as_(), + } + } + + /// Cast to a quantity with the same dimension and unit but a different underlying + /// storage type allowing for precision loss and truncation. + /// + /// # Examples + #[cfg_attr(all(feature = "si", feature = "f32", feature = "i32"), doc = " ```rust")] + #[cfg_attr(not(all(feature = "si", feature = "f32", feature = "i32")), doc = " ```rust,ignore")] + /// # use uom::si::{f32, i32}; + /// # use uom::si::time::second; + /// let t1 = f32::Time::new::(1.5); + /// let t2 = f32::Time::new::(1.0e32); + /// + /// let t1: Option = t1.cast(); + /// let t2: Option = t2.cast(); + /// + /// assert_eq!(t1, Some(i32::Time::new::(1))); + /// assert_eq!(t2, None); + /// ``` + #[inline(always)] + pub fn cast(self) -> Option, W>> + where + V: $crate::num::NumCast, + $units: Units, + W: $crate::num::Num + $crate::Conversion + $crate::num::NumCast, + { + Some(Quantity { + dimension: $crate::lib::marker::PhantomData, + units: $crate::lib::marker::PhantomData, + value: $crate::num::NumCast::from(self.value)?, + }) + } + } + #[doc(hidden)] macro_rules! impl_ops { (