1pub mod acl;
7pub mod fsflags;
8pub mod mac;
9pub mod mount;
10pub mod path;
11pub mod subject;
12
13use mac::MacState;
14use mount::MountTable;
15use path::PathComponent;
16use serde::Serialize;
17use subject::ResolvedSubject;
18
19use crate::operation::Operation;
20
21#[must_use = "probed values must be inspected -- ignoring them risks false-green results"]
27#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
28#[serde(tag = "status", content = "value")]
29#[non_exhaustive]
30pub enum Probe<T> {
31 Known(T),
33 Unknown,
35 Inaccessible,
37}
38
39impl<T> Probe<T> {
40 #[must_use = "map returns a new Probe without modifying the original"]
42 pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Probe<U> {
43 match self {
44 Self::Known(v) => Probe::Known(f(v)),
45 Self::Unknown => Probe::Unknown,
46 Self::Inaccessible => Probe::Inaccessible,
47 }
48 }
49
50 #[must_use]
52 pub fn known(&self) -> Option<&T> {
53 match self {
54 Self::Known(v) => Some(v),
55 Self::Unknown | Self::Inaccessible => None,
56 }
57 }
58
59 #[must_use]
61 pub fn is_known(&self) -> bool {
62 matches!(self, Self::Known(_))
63 }
64
65 #[must_use = "as_ref returns a new Probe without modifying the original"]
67 pub fn as_ref(&self) -> Probe<&T> {
68 match self {
69 Self::Known(v) => Probe::Known(v),
70 Self::Unknown => Probe::Unknown,
71 Self::Inaccessible => Probe::Inaccessible,
72 }
73 }
74}
75
76#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
82pub struct SystemState {
83 pub subject: ResolvedSubject,
85 pub walk: Vec<PathComponent>,
87 pub mounts: MountTable,
89 pub operation: Operation,
91 pub mac_state: MacState,
93}
94
95#[cfg(test)]
96mod tests {
97 use super::*;
98
99 #[test]
100 fn probe_map_transforms_known_value() {
101 let probe = Probe::Known(42);
102 let mapped = probe.map(|v| v * 2);
103 assert_eq!(mapped, Probe::Known(84));
104 }
105
106 #[test]
107 fn probe_map_preserves_unknown() {
108 let probe: Probe<i32> = Probe::Unknown;
109 let mapped = probe.map(|v| v * 2);
110 assert_eq!(mapped, Probe::<i32>::Unknown);
111 }
112
113 #[test]
114 fn probe_map_preserves_inaccessible() {
115 let probe: Probe<i32> = Probe::Inaccessible;
116 let mapped = probe.map(|v| v * 2);
117 assert_eq!(mapped, Probe::<i32>::Inaccessible);
118 }
119
120 #[test]
121 fn probe_known_returns_some_for_known() {
122 let probe = Probe::Known(42);
123 assert_eq!(probe.known(), Some(&42));
124 }
125
126 #[test]
127 fn probe_known_returns_none_for_unknown() {
128 let probe: Probe<i32> = Probe::Unknown;
129 assert_eq!(probe.known(), None);
130 }
131
132 #[test]
133 fn probe_known_returns_none_for_inaccessible() {
134 let probe: Probe<i32> = Probe::Inaccessible;
135 assert_eq!(probe.known(), None);
136 }
137
138 #[test]
139 fn probe_is_known_true_for_known() {
140 let probe = Probe::Known(42);
141 assert!(probe.is_known());
142 }
143
144 #[test]
145 fn probe_is_known_false_for_unknown() {
146 let probe: Probe<i32> = Probe::Unknown;
147 assert!(!probe.is_known());
148 }
149
150 #[test]
151 fn probe_is_known_false_for_inaccessible() {
152 let probe: Probe<i32> = Probe::Inaccessible;
153 assert!(!probe.is_known());
154 }
155
156 #[test]
157 fn probe_as_ref_known_returns_reference() {
158 let probe = Probe::Known(42);
159 assert_eq!(probe.as_ref(), Probe::Known(&42));
160 }
161
162 #[test]
163 fn probe_as_ref_unknown_stays_unknown() {
164 let probe: Probe<i32> = Probe::Unknown;
165 assert_eq!(probe.as_ref(), Probe::<&i32>::Unknown);
166 }
167
168 #[test]
169 fn probe_as_ref_inaccessible_stays_inaccessible() {
170 let probe: Probe<i32> = Probe::Inaccessible;
171 assert_eq!(probe.as_ref(), Probe::<&i32>::Inaccessible);
172 }
173}