pub mod acl;
pub mod fsflags;
pub mod mac;
pub mod mount;
pub mod path;
pub mod subject;
use mac::MacState;
use mount::MountTable;
use path::PathComponent;
use serde::Serialize;
use subject::ResolvedSubject;
use crate::operation::Operation;
#[must_use = "probed values must be inspected -- ignoring them risks false-green results"]
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
#[serde(tag = "status", content = "value")]
#[non_exhaustive]
pub enum Probe<T> {
Known(T),
Unknown,
Inaccessible,
}
impl<T> Probe<T> {
#[must_use = "map returns a new Probe without modifying the original"]
pub fn map<U, F: FnOnce(T) -> U>(self, f: F) -> Probe<U> {
match self {
Self::Known(v) => Probe::Known(f(v)),
Self::Unknown => Probe::Unknown,
Self::Inaccessible => Probe::Inaccessible,
}
}
#[must_use]
pub fn known(&self) -> Option<&T> {
match self {
Self::Known(v) => Some(v),
Self::Unknown | Self::Inaccessible => None,
}
}
#[must_use]
pub fn is_known(&self) -> bool {
matches!(self, Self::Known(_))
}
#[must_use = "as_ref returns a new Probe without modifying the original"]
pub fn as_ref(&self) -> Probe<&T> {
match self {
Self::Known(v) => Probe::Known(v),
Self::Unknown => Probe::Unknown,
Self::Inaccessible => Probe::Inaccessible,
}
}
}
#[derive(Debug, Clone, PartialEq, Eq, Serialize)]
pub struct SystemState {
pub subject: ResolvedSubject,
pub walk: Vec<PathComponent>,
pub mounts: MountTable,
pub operation: Operation,
pub mac_state: MacState,
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn probe_map_transforms_known_value() {
let probe = Probe::Known(42);
let mapped = probe.map(|v| v * 2);
assert_eq!(mapped, Probe::Known(84));
}
#[test]
fn probe_map_preserves_unknown() {
let probe: Probe<i32> = Probe::Unknown;
let mapped = probe.map(|v| v * 2);
assert_eq!(mapped, Probe::<i32>::Unknown);
}
#[test]
fn probe_map_preserves_inaccessible() {
let probe: Probe<i32> = Probe::Inaccessible;
let mapped = probe.map(|v| v * 2);
assert_eq!(mapped, Probe::<i32>::Inaccessible);
}
#[test]
fn probe_known_returns_some_for_known() {
let probe = Probe::Known(42);
assert_eq!(probe.known(), Some(&42));
}
#[test]
fn probe_known_returns_none_for_unknown() {
let probe: Probe<i32> = Probe::Unknown;
assert_eq!(probe.known(), None);
}
#[test]
fn probe_known_returns_none_for_inaccessible() {
let probe: Probe<i32> = Probe::Inaccessible;
assert_eq!(probe.known(), None);
}
#[test]
fn probe_is_known_true_for_known() {
let probe = Probe::Known(42);
assert!(probe.is_known());
}
#[test]
fn probe_is_known_false_for_unknown() {
let probe: Probe<i32> = Probe::Unknown;
assert!(!probe.is_known());
}
#[test]
fn probe_is_known_false_for_inaccessible() {
let probe: Probe<i32> = Probe::Inaccessible;
assert!(!probe.is_known());
}
#[test]
fn probe_as_ref_known_returns_reference() {
let probe = Probe::Known(42);
assert_eq!(probe.as_ref(), Probe::Known(&42));
}
#[test]
fn probe_as_ref_unknown_stays_unknown() {
let probe: Probe<i32> = Probe::Unknown;
assert_eq!(probe.as_ref(), Probe::<&i32>::Unknown);
}
#[test]
fn probe_as_ref_inaccessible_stays_inaccessible() {
let probe: Probe<i32> = Probe::Inaccessible;
assert_eq!(probe.as_ref(), Probe::<&i32>::Inaccessible);
}
}