Skip to main content

use_motion/
lib.rs

1#![forbid(unsafe_code)]
2#![doc = include_str!("../README.md")]
3
4//! Basic kinematics helpers.
5
6use core::fmt;
7
8pub mod prelude;
9
10#[derive(Debug, Clone, Copy, PartialEq, Eq)]
11pub enum MotionError {
12    NonPositiveDuration,
13}
14
15impl fmt::Display for MotionError {
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 MotionError {}
24
25#[must_use]
26pub const fn distance(speed: f64, time: f64) -> f64 {
27    speed * time
28}
29
30#[must_use]
31pub const fn displacement(initial_position: f64, final_position: f64) -> f64 {
32    final_position - initial_position
33}
34
35#[must_use]
36pub const fn final_velocity(initial_velocity: f64, acceleration: f64, time: f64) -> f64 {
37    initial_velocity + acceleration * time
38}
39
40/// Computes average speed from traveled distance and elapsed duration.
41///
42/// # Errors
43///
44/// Returns [`MotionError::NonPositiveDuration`] when `duration` is less than or equal to zero.
45pub fn average_speed(distance: f64, duration: f64) -> Result<f64, MotionError> {
46    if duration <= 0.0 {
47        Err(MotionError::NonPositiveDuration)
48    } else {
49        Ok(distance / duration)
50    }
51}
52
53#[cfg(test)]
54#[allow(clippy::float_cmp)]
55mod tests {
56    use super::{MotionError, average_speed, displacement, distance, final_velocity};
57
58    #[test]
59    fn motion_helpers_cover_common_kinematics() -> Result<(), MotionError> {
60        assert_eq!(distance(5.0, 4.0), 20.0);
61        assert_eq!(displacement(3.0, 9.0), 6.0);
62        assert_eq!(final_velocity(2.0, 3.0, 4.0), 14.0);
63        assert_eq!(average_speed(100.0, 10.0)?, 10.0);
64        Ok(())
65    }
66
67    #[test]
68    fn average_speed_requires_positive_duration() {
69        assert_eq!(
70            average_speed(100.0, 0.0),
71            Err(MotionError::NonPositiveDuration)
72        );
73    }
74}