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
//! `Runnable` trait.

#[doc(hidden)]
pub use abscissa_derive::Runnable;

/// `Runnable` is a common trait for things which can be run without any
/// arguments.
///
/// Its primary intended purpose is for use in conjunction with `Command`.
pub trait Runnable {
    /// Run this `Runnable`
    fn run(&self);
}

/// `RunnableMut` is a `Runnable` that takes a mutable reference to `self`.
pub trait RunnableMut {
    /// Run this `RunnableMut`
    fn run(&mut self);
}

impl Runnable for Box<dyn Fn() -> ()> {
    fn run(&self) {
        self();
    }
}

impl RunnableMut for Box<dyn FnMut() -> ()> {
    fn run(&mut self) {
        self();
    }
}

#[cfg(test)]
mod tests {
    use crate::Runnable;
    use std::sync::Mutex;

    #[allow(dead_code)]
    #[derive(Runnable)]
    enum TestEnum {
        A(VariantA),
        B(VariantB),
    }

    #[allow(dead_code)]
    struct VariantA {}

    impl Runnable for VariantA {
        fn run(&self) {
            panic!("don't call this!")
        }
    }

    #[derive(Default)]
    struct VariantB {
        called: Mutex<bool>,
    }

    impl VariantB {
        fn was_called(&self) -> bool {
            let called = self.called.lock().unwrap();
            *called
        }
    }

    impl Runnable for VariantB {
        fn run(&self) {
            let mut called = self.called.lock().unwrap();
            *called = true;
        }
    }

    #[test]
    fn custom_derive_test() {
        let variant_b = VariantB::default();
        assert!(!variant_b.was_called());

        let ex = TestEnum::B(variant_b);
        ex.run();

        let variant_b = match ex {
            TestEnum::A(_) => panic!("this shouldn't be!"),
            TestEnum::B(b) => b,
        };
        assert!(variant_b.was_called());
    }
}