mod cmp;
mod convert;
use crate::FloatError;
#[derive(Debug, Default, Clone, Copy)]
pub struct GuardedF32(pub(crate) f32);
impl GuardedF32 {
pub const fn new(value: f32) -> Result<Self, FloatError> {
if value.is_finite() {
Ok(Self(value))
} else {
Err(if value.is_nan() {
FloatError::NaN
} else {
FloatError::Infinity
})
}
}
}
impl std::fmt::Display for GuardedF32 {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.0)
}
}
#[cfg(test)]
mod tests {
#![allow(clippy::float_cmp)]
use super::*;
use crate::f32::tests::{invalid_f32, valid_f32};
use proptest::prelude::*;
proptest! {
#[test]
fn test_new_valid(a in valid_f32()) {
prop_assert_eq!(GuardedF32::new(a), Ok(GuardedF32(a)));
prop_assert_eq!(GuardedF32::new(a).map(f32::from), Ok(a));
prop_assert_eq!(*GuardedF32::new(a).unwrap(), a);
}
#[test]
fn test_new_invalid(a in invalid_f32()) {
let err = if a.is_nan() {
FloatError::NaN
} else {
FloatError::Infinity
};
prop_assert_eq!(GuardedF32::new(a), Err(err));
}
#[test]
fn test_display(a in any::<f32>()) {
let checked_a = GuardedF32::new(a);
if let Ok(guarded_a) = checked_a {
prop_assert_eq!(guarded_a.to_string(), a.to_string());
} else {
prop_assert!(a.is_nan() || a.is_infinite());
}
}
}
}