1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
use core::time::Duration;
use void::Void;

/// An interface to the stepper motor.
pub trait Device {
    /// The type of error that may be encountered when taking a step.
    ///
    /// Use `!` (or [`void::Void`] on stable) if stepping can never fail.
    type Error;

    fn step(&mut self, ctx: &StepContext) -> Result<(), Self::Error>;
}

impl<'a, D: Device> Device for &'a mut D {
    type Error = D::Error;

    fn step(&mut self, ctx: &StepContext) -> Result<(), Self::Error> {
        (*self).step(ctx)
    }
}

/// Extra contextual information passed to a [`Device`] when its
/// [`Device::step()`] method is invoked.
#[derive(Debug, Clone, PartialEq)]
pub struct StepContext {
    /// The new position, in steps.
    pub position: i64,
    /// The time (as dictated by [`crate::SystemClock::elapsed()`]) this step
    /// was taken.
    pub step_time: Duration,
}

/// A [`Device`] which will call one function for a forward step, and another
/// for a backward one.
///
/// See [`fallible_func_device()`] for a version which accepts fallible
/// callbacks.
pub fn func_device<F, B, T>(
    forward: F,
    backward: B,
) -> impl Device<Error = Void>
where
    F: FnMut() -> T,
    B: FnMut() -> T,
{
    Infallible {
        forward,
        backward,
        previous_position: 0,
    }
}

struct Infallible<F, B> {
    previous_position: i64,
    forward: F,
    backward: B,
}

impl<F, B, T> Device for Infallible<F, B>
where
    F: FnMut() -> T,
    B: FnMut() -> T,
{
    type Error = Void;

    #[inline]
    fn step(&mut self, ctx: &StepContext) -> Result<(), Self::Error> {
        let diff = ctx.position - self.previous_position;

        if diff > 0 {
            (self.forward)();
        } else if diff < 0 {
            (self.backward)();
        }

        self.previous_position = ctx.position;
        Ok(())
    }
}

/// A device which uses callbacks which may fail.
///
/// See [`func_device()`] for a version which uses infallible callbacks.
pub fn fallible_func_device<F, B, T, E>(
    forward: F,
    backward: B,
) -> impl Device<Error = E>
where
    F: FnMut() -> Result<T, E>,
    B: FnMut() -> Result<T, E>,
{
    Fallible {
        forward,
        backward,
        previous_position: 0,
    }
}

struct Fallible<F, B> {
    previous_position: i64,
    forward: F,
    backward: B,
}

impl<F, B, T, E> Device for Fallible<F, B>
where
    F: FnMut() -> Result<T, E>,
    B: FnMut() -> Result<T, E>,
{
    type Error = E;

    #[inline]
    fn step(&mut self, ctx: &StepContext) -> Result<(), Self::Error> {
        let diff = ctx.position - self.previous_position;

        if diff > 0 {
            (self.forward)()?;
        } else if diff < 0 {
            (self.backward)()?;
        }

        self.previous_position = ctx.position;
        Ok(())
    }
}