1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4use 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
35pub 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}