use crate::audio::WHISPER_SAMPLE_RATE;
use crate::error::{Result, UserError};
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct SampleRateHz(u32);
impl SampleRateHz {
pub fn try_new(hz: u32) -> Result<Self> {
if hz == 0 {
return Err(UserError::Other {
message: "sample rate must be positive".into(),
}
.into());
}
Ok(Self(hz))
}
pub fn whisper() -> Self {
Self(WHISPER_SAMPLE_RATE)
}
pub fn get(self) -> u32 {
self.0
}
pub fn is_whisper(self) -> bool {
self.0 == WHISPER_SAMPLE_RATE
}
}
#[derive(Debug, Clone, Copy, PartialEq)]
pub struct FiniteDurationSecs(f64);
impl FiniteDurationSecs {
pub fn try_new(secs: f64) -> Result<Self> {
if !secs.is_finite() || secs < 0.0 {
return Err(UserError::Other {
message: format!("duration must be finite and non-negative (got {secs})"),
}
.into());
}
Ok(Self(secs))
}
pub fn get(self) -> f64 {
self.0
}
pub fn zero() -> Self {
Self(0.0)
}
}
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct ModelId(String);
impl ModelId {
pub fn try_new(id: impl Into<String>) -> Result<Self> {
let s = id.into();
let t = s.trim();
if t.is_empty() {
return Err(UserError::Other {
message: "model id must be non-empty".into(),
}
.into());
}
if t.chars().any(|c| c.is_control()) {
return Err(UserError::Other {
message: "model id must not contain control characters".into(),
}
.into());
}
Ok(Self(t.to_string()))
}
pub fn as_str(&self) -> &str {
&self.0
}
pub fn into_inner(self) -> String {
self.0
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn sample_rate_rejects_zero() {
assert!(SampleRateHz::try_new(0).is_err());
assert_eq!(SampleRateHz::whisper().get(), WHISPER_SAMPLE_RATE);
}
#[test]
fn duration_rejects_nan() {
assert!(FiniteDurationSecs::try_new(f64::NAN).is_err());
assert!(FiniteDurationSecs::try_new(-1.0).is_err());
assert_eq!(FiniteDurationSecs::try_new(1.5).unwrap().get(), 1.5);
}
#[test]
fn model_id_rejects_empty_and_control() {
assert!(ModelId::try_new("").is_err());
assert!(ModelId::try_new(" ").is_err());
assert!(ModelId::try_new("a\nb").is_err());
assert_eq!(ModelId::try_new("tiny-q5_1").unwrap().as_str(), "tiny-q5_1");
}
}