use std::fmt;
#[non_exhaustive]
#[derive(Debug, Clone, PartialEq)]
pub enum EncoderError {
NonFiniteRate { parameter: &'static str },
RateOrder,
InvalidRange { parameter: &'static str },
CountMustBePositive { parameter: &'static str },
NonPositiveOrNonFinite { parameter: &'static str },
NonNegativeFinite { parameter: &'static str },
NumChannelsTooLarge,
HistoryDepthTooSmall { minimum: usize },
StateLengthMismatch {
left: &'static str,
right: &'static str,
},
HistoryLengthExceedsDepth { channel: usize },
WindowMustBePositive { parameter: &'static str },
}
impl fmt::Display for EncoderError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::NonFiniteRate { parameter } => write!(f, "{parameter} must be finite"),
Self::RateOrder => write!(f, "base_rate must be less than or equal to max_rate"),
Self::InvalidRange { parameter } => write!(
f,
"{parameter} must be finite and min must be less than max"
),
Self::CountMustBePositive { parameter } => {
write!(f, "{parameter} must be greater than 0")
}
Self::NonPositiveOrNonFinite { parameter } => {
write!(f, "{parameter} must be finite and greater than 0")
}
Self::NonNegativeFinite { parameter } => {
write!(f, "{parameter} must be finite and non-negative")
}
Self::NumChannelsTooLarge => write!(
f,
"num_channels exceeds u16::MAX as usize + 1 (max addressable spike channels)"
),
Self::HistoryDepthTooSmall { minimum } => {
write!(f, "history_depth must be at least {minimum}")
}
Self::StateLengthMismatch { left, right } => {
write!(f, "mismatched {left} and {right} lengths")
}
Self::HistoryLengthExceedsDepth { channel } => {
write!(f, "history channel {channel} length exceeds history_depth")
}
Self::WindowMustBePositive { parameter } => {
write!(f, "{parameter} must be greater than 0")
}
}
}
}
impl std::error::Error for EncoderError {}
pub(crate) const MAX_SPIKE_CHANNELS: usize = u16::MAX as usize + 1;
pub(crate) fn validate_range(
parameter: &'static str,
range: (f32, f32),
) -> Result<(), EncoderError> {
if range.0.is_finite() && range.1.is_finite() && range.0 < range.1 {
Ok(())
} else {
Err(EncoderError::InvalidRange { parameter })
}
}
pub(crate) fn validate_range_f32_span(
parameter: &'static str,
range: (f32, f32),
) -> Result<(), EncoderError> {
validate_range(parameter, range)?;
if (range.1 - range.0).is_finite() {
Ok(())
} else {
Err(EncoderError::InvalidRange { parameter })
}
}
pub(crate) fn validate_channel_count(num_channels: usize) -> Result<(), EncoderError> {
if num_channels <= MAX_SPIKE_CHANNELS {
Ok(())
} else {
Err(EncoderError::NumChannelsTooLarge)
}
}
pub(crate) fn validate_non_negative_finite(
parameter: &'static str,
value: f32,
) -> Result<(), EncoderError> {
if value.is_finite() && value >= 0.0 {
Ok(())
} else {
Err(EncoderError::NonNegativeFinite { parameter })
}
}