use core::error::Error;
use core::fmt::{Display, Formatter};
#[derive(Debug, Copy, Clone)]
pub enum FrequencyLimit {
All,
Min(f32),
Max(f32),
Range(f32, f32),
}
impl FrequencyLimit {
#[inline]
#[must_use]
pub const fn maybe_min(&self) -> Option<f32> {
match self {
Self::Min(min) => Some(*min),
Self::Range(min, _) => Some(*min),
_ => None,
}
}
#[inline]
#[must_use]
pub const fn maybe_max(&self) -> Option<f32> {
match self {
Self::Max(max) => Some(*max),
Self::Range(_, max) => Some(*max),
_ => None,
}
}
#[inline]
#[must_use]
pub fn min(&self) -> f32 {
self.maybe_min().expect("Must contain a value!")
}
#[inline]
#[must_use]
pub fn max(&self) -> f32 {
self.maybe_max().expect("Must contain a value!")
}
pub fn verify(&self, max_detectable_frequency: f32) -> Result<(), FrequencyLimitError> {
match self {
Self::All => Ok(()),
Self::Min(x) | Self::Max(x) => {
if *x < 0.0 {
Err(FrequencyLimitError::ValueBelowMinimum(*x))
} else if *x > max_detectable_frequency {
Err(FrequencyLimitError::ValueAboveNyquist(*x))
} else {
Ok(())
}
}
Self::Range(min, max) => {
Self::Min(*min).verify(max_detectable_frequency)?;
Self::Max(*max).verify(max_detectable_frequency)?;
if min > max {
Err(FrequencyLimitError::InvalidRange(*min, *max))
} else {
Ok(())
}
}
}
}
}
#[derive(Debug)]
pub enum FrequencyLimitError {
ValueBelowMinimum(f32),
ValueAboveNyquist(f32),
InvalidRange(f32, f32),
}
impl Display for FrequencyLimitError {
fn fmt(&self, f: &mut Formatter<'_>) -> core::fmt::Result {
match self {
Self::ValueBelowMinimum(x) => write!(f, "Value below minimum: {x}"),
Self::ValueAboveNyquist(x) => write!(f, "Value above Nyquist: {x}"),
Self::InvalidRange(min, max) => write!(f, "Invalid range: {min} <= x <= {max}"),
}
}
}
impl Error for FrequencyLimitError {}
#[cfg(test)]
mod tests {
use crate::FrequencyLimit;
#[test]
fn test_panic_min_below_minimum() {
let _ = FrequencyLimit::Min(-1.0).verify(0.0).unwrap_err();
}
#[test]
fn test_panic_min_above_nyquist() {
let _ = FrequencyLimit::Min(1.0).verify(0.0).unwrap_err();
}
#[test]
fn test_panic_max_below_minimum() {
let _ = FrequencyLimit::Max(-1.0).verify(0.0).unwrap_err();
}
#[test]
fn test_panic_max_above_nyquist() {
let _ = FrequencyLimit::Max(1.0).verify(0.0).unwrap_err();
}
#[test]
fn test_panic_range_min() {
let _ = FrequencyLimit::Range(-1.0, 0.0).verify(0.0).unwrap_err();
}
#[test]
fn test_panic_range_max() {
let _ = FrequencyLimit::Range(0.0, 1.0).verify(0.0).unwrap_err();
}
#[test]
fn test_panic_range_order() {
let _ = FrequencyLimit::Range(0.0, -1.0).verify(0.0).unwrap_err();
}
#[test]
fn test_ok() {
FrequencyLimit::Min(50.0).verify(100.0).unwrap();
FrequencyLimit::Max(50.0).verify(100.0).unwrap();
FrequencyLimit::Range(50.0, 50.0).verify(100.0).unwrap();
FrequencyLimit::Range(50.0, 70.0).verify(100.0).unwrap();
}
}