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
126
127
128
129
130
131
132
133
134
135
136
137
//! Nodes in this module are intended for testing. While they're being
//! used to internally test this library they could also prove to be useful
//! for testing custom node types in user code.
use std::{cell::RefCell, rc::Rc};

use crate::prelude::*;

/// Node that will panic upon being dropped if it hasn't ticked
/// at least once.
///
/// Inspired by https://github.com/danieleades/aspen/blob/master/src/std_nodes/testing.rs
#[derive(Default)]
pub struct YesTick {
    pub ticked: bool,
}

impl YesTick {
    pub fn action<T>() -> Node<T> {
        Node::stateful_action("yes", Box::new(YesTick::default()))
    }
}

impl<T> StatefulAction<T> for YesTick {
    fn tick(&mut self, _data: &mut T) -> Status {
        self.ticked = true;
        Status::Success
    }

    fn reset(&mut self) {
        // no-op
    }
}

impl Drop for YesTick {
    fn drop(&mut self) {
        if !self.ticked {
            panic!("YesTick dropped without being ticked");
        }
    }
}

/// Node that will panic when it ticks.
///
/// Inspired by https://github.com/danieleades/aspen/blob/master/src/std_nodes/testing.rs
#[derive(Default)]
pub struct NoTick;

impl NoTick {
    pub fn action<T>() -> Node<T> {
        Node::stateful_action("no", Box::new(NoTick::default()))
    }
}

impl<T> StatefulAction<T> for NoTick {
    fn tick(&mut self, _data: &mut T) -> Status {
        panic!("NoTick node should never be ticked");
    }

    fn reset(&mut self) {
        // no-op to allow testing reset on bigger trees
    }
}

/// Node that always runs.
pub struct AlwaysRunning;

impl AlwaysRunning {
    pub fn action<T>() -> Node<T> {
        Node::action("running", |_| Status::Running)
    }
}

/// Node that always returns a given status when ticked, but exposes the status
/// to be modified from the outside.
pub struct ConstAction {
    pub return_status: Rc<RefCell<Status>>,
}

impl ConstAction {
    pub fn new(status: Status) -> Self {
        Self {
            return_status: Rc::new(RefCell::new(status)),
        }
    }
}

impl<T> StatefulAction<T> for ConstAction {
    fn tick(&mut self, _data: &mut T) -> Status {
        *self.return_status.borrow()
    }

    fn reset(&mut self) {}
}
// impl<T> StatefulAction<T> for AlwaysRunning {
//     fn tick(&mut self, _data: &mut T) -> Status {
//         Status::Running
//     }
//
//     fn reset(&mut self) {
//         panic!("AlwaysRunning should never be reset");
//     }
// }

#[derive(Default)]
pub struct Counter {
    pub value: Rc<RefCell<i32>>,
    resettable: bool,
}

impl Counter {
    pub fn action<T>(resettable: bool) -> (Rc<RefCell<Node<T>>>, Rc<RefCell<i32>>) {
        let value = Rc::new(RefCell::new(0));
        (
            Rc::new(RefCell::new(Node::stateful_action(
                "counter",
                Box::new(Self {
                    value: value.clone(),
                    resettable,
                }),
            ))),
            value,
        )
    }
}

impl<T> StatefulAction<T> for Counter {
    fn tick(&mut self, _data: &mut T) -> Status {
        *self.value.borrow_mut() += 1;
        Status::Success
    }

    fn reset(&mut self) {
        if self.resettable {
            *self.value.borrow_mut() = 0;
        }
    }
}