tor_memquota/if_enabled.rs
1//! Helper type for disabling memory tracking when not wanted
2
3use crate::internal_prelude::*;
4
5/// Either `T`, if we're enabled, or nothing if we're no-op
6///
7/// Used for runtime control of whether the memory quota is enabled:
8/// we support explicitly creating a no-op tracker
9/// with [`MemoryQuotaTracker::new_noop`](crate::MemoryQuotaTracker::new_noop).
10///
11/// We use this rather than just `Option` because we also have data structures
12/// (trackers, `Account`s and so on)
13/// which have been torn down, or are "dummy" or "dangling",
14/// which are supposed to return errors rather than no-op successes.
15#[derive(Clone, Debug, Eq, PartialEq)]
16pub(crate) enum IfEnabled<T> {
17 /// We're enabled, and supposed to be tracking memory
18 ///
19 /// The 2nd member causes this variant to prove that tracking is enabled.
20 /// If tracking is disabled at compile time, this variant is uninhabited
21 /// and the whole `IfEnabled` becomes a unit.
22 Enabled(T, EnabledToken),
23
24 /// We're inenabled and everything should be a lightweight no-op
25 Noop,
26}
27
28use IfEnabled::*;
29
30impl<T> IfEnabled<T> {
31 /// Convert to `Option`: return `Some` if this is `Enabled`
32 pub(crate) fn into_enabled(self) -> Option<T> {
33 match self {
34 Enabled(y, _e) => Some(y),
35 Noop => None,
36 }
37 }
38
39 /// Take reference; analogous to `Option::as_ref`
40 pub(crate) fn as_ref(&self) -> IfEnabled<&T> {
41 match self {
42 Enabled(y, e) => Enabled(y, *e),
43 Noop => Noop,
44 }
45 }
46
47 /// Take reference and convert to `Option`
48 ///
49 /// Convenience helper equivalent to `.as_ref().into_enabled()`.
50 pub(crate) fn as_enabled(&self) -> Option<&T> {
51 self.as_ref().into_enabled()
52 }
53
54 /// Return the contents of the `Enabled`, or declare it a [`Bug`]
55 #[track_caller]
56 pub(crate) fn enabled_or_bug(self) -> Result<T, Bug> {
57 match self {
58 Enabled(y, _e) => Ok(y),
59 Noop => Err(internal!("IfEnabled unexpectedly Noop")),
60 }
61 }
62}