Skip to main content

use_power/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4//! Average, mechanical, and electrical power helpers.
5
6use core::fmt;
7
8pub mod prelude;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum PowerError {
12    NonPositiveDuration,
13}
14
15impl fmt::Display for PowerError {
16    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
17        match self {
18            Self::NonPositiveDuration => formatter.write_str("duration must be greater than zero"),
19        }
20    }
21}
22
23impl std::error::Error for PowerError {}
24
25#[must_use]
26pub const fn mechanical_power(force: f64, velocity: f64) -> f64 {
27    force * velocity
28}
29
30#[must_use]
31pub const fn electrical_power(voltage: f64, current: f64) -> f64 {
32    voltage * current
33}
34
35/// Computes average power from total work and elapsed duration.
36///
37/// # Errors
38///
39/// Returns [`PowerError::NonPositiveDuration`] when `duration` is less than or equal to zero.
40pub fn average_power(work: f64, duration: f64) -> Result<f64, PowerError> {
41    if duration <= 0.0 {
42        Err(PowerError::NonPositiveDuration)
43    } else {
44        Ok(work / duration)
45    }
46}
47
48#[cfg(test)]
49#[allow(clippy::float_cmp)]
50mod tests {
51    use super::{PowerError, average_power, electrical_power, mechanical_power};
52
53    #[test]
54    fn power_helpers_cover_common_calculations() -> Result<(), PowerError> {
55        assert_eq!(mechanical_power(10.0, 3.0), 30.0);
56        assert_eq!(electrical_power(12.0, 2.0), 24.0);
57        assert_eq!(average_power(120.0, 6.0)?, 20.0);
58        Ok(())
59    }
60
61    #[test]
62    fn average_power_requires_positive_duration() {
63        assert_eq!(
64            average_power(120.0, 0.0),
65            Err(PowerError::NonPositiveDuration)
66        );
67    }
68}