Skip to main content

tor_proto/util/sink_blocker/
boolean_policy.rs

1//! Implement a sink-blocking policy based on a simple blocked/unblocked status.
2
3use super::Policy;
4use tor_error::{Bug, internal};
5
6/// A simple two-state sink-blocking [`Policy`] .
7#[derive(Debug, Clone, Copy)]
8pub(crate) enum BooleanPolicy {
9    /// The sink is blocked.
10    Blocked,
11    /// The sink is not blocked.
12    Unblocked,
13}
14
15impl Policy for BooleanPolicy {
16    fn is_blocking(&self) -> bool {
17        matches!(self, BooleanPolicy::Blocked)
18    }
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    fn take_one(&mut self) -> Result<(), Bug> {
24        match self {
25            BooleanPolicy::Blocked => {
26                Err(internal!("Tried to take_one on a blocked BooleanPolicy!"))
27            }
28            BooleanPolicy::Unblocked => Ok(()),
29        }
30    }
31}
32
33impl<S> super::SinkBlocker<S, BooleanPolicy> {
34    /// Put this `SinkBlocker` into a blocked state.
35    pub(crate) fn set_blocked(&mut self) {
36        self.update_policy(BooleanPolicy::Blocked);
37    }
38
39    /// Put this `SinkBlocker` into an unblocked state.
40    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        self.update_policy(BooleanPolicy::Unblocked);
45    }
46}
47
48#[cfg(test)]
49mod 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}