pub mod commands;
pub mod events;
pub use commands::Command;
pub use events::{ClientEvent, ConnectionState, DisconnectReason, Event};
use serde::{Deserialize, Serialize};
pub trait Request: std::fmt::Debug {
type Response;
fn into_command(self) -> Command;
fn extract(event: &Event, cmd: &Command) -> Option<Self::Response>;
}
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize)]
pub struct Frequency(pub u64);
impl Frequency {
#[must_use]
pub const fn from_hz(hz: u64) -> Self {
Self(hz)
}
#[must_use]
pub const fn from_khz(khz: u64) -> Self {
Self(khz * 1_000)
}
#[allow(
clippy::cast_precision_loss,
clippy::cast_possible_truncation,
clippy::cast_sign_loss
)]
#[must_use]
pub fn from_mhz(mhz: f64) -> Self {
Self((mhz * 1_000_000.0f64).round() as u64)
}
#[must_use]
pub const fn as_hz(&self) -> u64 {
self.0
}
#[must_use]
pub const fn as_khz(&self) -> u64 {
self.0 / 1_000
}
#[allow(clippy::cast_precision_loss)]
#[must_use]
pub fn as_mhz(&self) -> f64 {
self.0 as f64 / 1_000_000.0f64
}
}
impl std::fmt::Debug for Frequency {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_tuple("Frequency")
.field(&format_args!("{:.3} MHz", self.as_mhz()))
.finish()
}
}
impl std::fmt::Display for Frequency {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "{:.3} MHz", self.as_mhz())
}
}
impl From<u64> for Frequency {
fn from(hz: u64) -> Self {
Self::from_hz(hz)
}
}
impl From<Frequency> for u64 {
fn from(freq: Frequency) -> Self {
freq.as_hz()
}
}
impl From<f64> for Frequency {
fn from(mhz: f64) -> Self {
Self::from_mhz(mhz)
}
}
impl From<Frequency> for f64 {
fn from(freq: Frequency) -> Self {
freq.as_mhz()
}
}
#[cfg(test)]
mod tests {
use super::*;
mod frequency {
use super::Frequency;
const EPSILON: f64 = 1e-6f64;
#[test]
fn from_hz() {
let f = Frequency::from_hz(132_600_000);
assert_eq!(f.as_hz(), 132_600_000);
assert_eq!(f.as_khz(), 132_600);
assert!((f.as_mhz() - 132.600f64).abs() < EPSILON);
}
#[test]
fn from_khz() {
let f = Frequency::from_khz(132_600);
assert_eq!(f.as_hz(), 132_600_000);
assert_eq!(f.as_khz(), 132_600);
assert!((f.as_mhz() - 132.600f64).abs() < EPSILON);
}
#[test]
fn from_mhz() {
let f = Frequency::from_mhz(132.600f64);
assert_eq!(f.as_hz(), 132_600_000);
assert_eq!(f.as_khz(), 132_600);
assert!((f.as_mhz() - 132.600f64).abs() < EPSILON);
}
#[test]
fn from_mhz_rounding() {
let f = Frequency::from_mhz(132.600_000_1f64);
assert_eq!(f.as_hz(), 132_600_000);
let f = Frequency::from_mhz(132.600_000_5f64);
assert_eq!(f.as_hz(), 132_600_001);
let f = Frequency::from_mhz(132.600_000_9f64);
assert_eq!(f.as_hz(), 132_600_001);
let f = Frequency::from_mhz(132.600_001_0f64);
assert_eq!(f.as_hz(), 132_600_001);
}
#[test]
fn from_u64() {
let f = Frequency::from_hz(132_600_000);
assert_eq!(Frequency::from(132_600_000u64), f);
}
#[test]
fn from_f64() {
let f = Frequency::from_hz(132_600_000);
assert_eq!(Frequency::from(132.600f64), f);
}
#[test]
fn u64_from() {
let f = Frequency::from_hz(132_600_000);
assert_eq!(u64::from(f), 132_600_000);
}
#[test]
fn f64_from() {
let f = Frequency::from_hz(132_600_000);
assert!((f64::from(f) - 132.600f64).abs() < EPSILON);
}
#[test]
fn debug() {
let f = Frequency::from_hz(132_600_000);
assert_eq!(format!("{f:?}"), "Frequency(132.600 MHz)");
}
#[test]
fn display() {
let f = Frequency::from_hz(132_600_000);
assert_eq!(format!("{f}"), "132.600 MHz");
}
}
}