1
//! Implement a sink-blocking policy based on a simple blocked/unblocked status.
2

            
3
use super::Policy;
4
use tor_error::{Bug, internal};
5

            
6
/// A simple two-state sink-blocking [`Policy`] .
7
#[derive(Debug, Clone, Copy)]
8
pub(crate) enum BooleanPolicy {
9
    /// The sink is blocked.
10
    Blocked,
11
    /// The sink is not blocked.
12
    Unblocked,
13
}
14

            
15
impl Policy for BooleanPolicy {
16
7184
    fn is_blocking(&self) -> bool {
17
7184
        matches!(self, BooleanPolicy::Blocked)
18
7184
    }
19

            
20
    // Correctness: This method doesn't change `self`.
21
    // There are no other methods taking `&mut self`.
22
    // Therefore the invariants of Policy are trivially preserved.
23
20
    fn take_one(&mut self) -> Result<(), Bug> {
24
20
        match self {
25
            BooleanPolicy::Blocked => {
26
2
                Err(internal!("Tried to take_one on a blocked BooleanPolicy!"))
27
            }
28
18
            BooleanPolicy::Unblocked => Ok(()),
29
        }
30
20
    }
31
}
32

            
33
impl<S> super::SinkBlocker<S, BooleanPolicy> {
34
    /// Put this `SinkBlocker` into a blocked state.
35
4
    pub(crate) fn set_blocked(&mut self) {
36
4
        self.update_policy(BooleanPolicy::Blocked);
37
4
    }
38

            
39
    /// Put this `SinkBlocker` into an unblocked state.
40
4
    pub(crate) fn set_unblocked(&mut self) {
41
        // Correctness: Note that this _replaces_ the Policy object,
42
        // and does not modify an existing Policy object.
43
        // This is the permitted way to make a SinkBlocker unblocked.
44
4
        self.update_policy(BooleanPolicy::Unblocked);
45
4
    }
46
}
47

            
48
#[cfg(test)]
49
mod test {
50
    // @@ begin test lint list maintained by maint/add_warning @@
51
    #![allow(clippy::bool_assert_comparison)]
52
    #![allow(clippy::clone_on_copy)]
53
    #![allow(clippy::dbg_macro)]
54
    #![allow(clippy::mixed_attributes_style)]
55
    #![allow(clippy::print_stderr)]
56
    #![allow(clippy::print_stdout)]
57
    #![allow(clippy::single_char_pattern)]
58
    #![allow(clippy::unwrap_used)]
59
    #![allow(clippy::unchecked_time_subtraction)]
60
    #![allow(clippy::useless_vec)]
61
    #![allow(clippy::needless_pass_by_value)]
62
    //! <!-- @@ end test lint list maintained by maint/add_warning @@ -->
63

            
64
    use super::*;
65

            
66
    #[test]
67
    fn boolean_policy() {
68
        let mut blocked = BooleanPolicy::Blocked;
69
        assert_eq!(blocked.is_blocking(), true);
70
        assert!(blocked.take_one().is_err());
71
        assert_eq!(blocked.is_blocking(), true);
72

            
73
        let mut unblocked = BooleanPolicy::Unblocked;
74
        assert_eq!(unblocked.is_blocking(), false);
75
        assert!(unblocked.take_one().is_ok());
76
        assert_eq!(unblocked.is_blocking(), false);
77
    }
78
}