use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(transparent)]
pub struct Weight {
pub(crate) value: f64,
}
impl Weight {
pub const ZERO: Self = Self { value: 0.0 };
#[must_use]
pub const fn value(self) -> f64 {
self.value
}
}
impl fmt::Display for Weight {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:.2}kg", self.value)
}
}
impl From<f64> for Weight {
fn from(value: f64) -> Self {
debug_assert!(
value.is_finite() && value >= 0.0,
"Weight must be finite and non-negative, got {value}"
);
Self { value }
}
}
impl std::ops::Add for Weight {
type Output = Self;
fn add(self, rhs: Self) -> Self {
Self {
value: self.value + rhs.value,
}
}
}
impl std::ops::AddAssign for Weight {
fn add_assign(&mut self, rhs: Self) {
self.value += rhs.value;
}
}
impl std::ops::Sub for Weight {
type Output = Self;
fn sub(self, rhs: Self) -> Self {
Self {
value: (self.value - rhs.value).max(0.0),
}
}
}
impl std::ops::SubAssign for Weight {
fn sub_assign(&mut self, rhs: Self) {
self.value = (self.value - rhs.value).max(0.0);
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(transparent)]
pub struct Speed {
pub(crate) value: f64,
}
impl Speed {
#[must_use]
pub const fn value(self) -> f64 {
self.value
}
}
impl fmt::Display for Speed {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:.2}m/s", self.value)
}
}
impl From<f64> for Speed {
fn from(value: f64) -> Self {
debug_assert!(
value.is_finite() && value >= 0.0,
"Speed must be finite and non-negative, got {value}"
);
Self { value }
}
}
#[derive(Debug, Clone, Copy, PartialEq, PartialOrd, Serialize, Deserialize)]
#[serde(transparent)]
pub struct Accel {
pub(crate) value: f64,
}
impl Accel {
#[must_use]
pub const fn value(self) -> f64 {
self.value
}
}
impl fmt::Display for Accel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(f, "{:.2}m/s²", self.value)
}
}
impl From<f64> for Accel {
fn from(value: f64) -> Self {
debug_assert!(
value.is_finite() && value >= 0.0,
"Accel must be finite and non-negative, got {value}"
);
Self { value }
}
}