hadoop_common/fs/permission/
fs_action.rs

1use core::fmt;
2use once_cell::sync::Lazy;
3
4/// Retain reference to value array.
5pub static FSACTION_VALUES: Lazy<Vec<FsAction>> = Lazy::new(FsAction::values);
6
7/// File system actions, e.g. read, write, etc.
8#[derive(Clone, Copy, PartialEq, Eq)]
9#[repr(u8)]
10pub enum FsAction {
11    // POSIX style
12    None,
13    Execute,
14    Write,
15    WriteExecute,
16    Read,
17    ReadExecute,
18    ReadWrite,
19    All,
20}
21
22impl FsAction {
23    fn values() -> Vec<Self> {
24        vec![
25            Self::None,
26            Self::Execute,
27            Self::Write,
28            Self::WriteExecute,
29            Self::Read,
30            Self::ReadExecute,
31            Self::ReadWrite,
32            Self::All,
33        ]
34    }
35
36    pub fn ordinal(&self) -> usize {
37        *self as usize
38    }
39
40    /// Symbolic representation
41    pub fn symbol(&self) -> String {
42        self.to_string()
43    }
44
45    /// Return true if this action implies that action.
46    pub fn implies(&self, that: Option<&FsAction>) -> bool {
47        match that {
48            Some(that) => self.ordinal() & that.ordinal() == that.ordinal(),
49            None => false,
50        }
51    }
52
53    /// AND operation.
54    pub fn and(&self, that: &FsAction) -> FsAction {
55        FSACTION_VALUES[self.ordinal() & that.ordinal()]
56    }
57
58    /// OR operation.
59    pub fn or(&self, that: &FsAction) -> FsAction {
60        FSACTION_VALUES[self.ordinal() | that.ordinal()]
61    }
62
63    /// NOT operation.
64    pub fn not(&self) -> FsAction {
65        FSACTION_VALUES[7 - self.ordinal()]
66    }
67
68    /// Get the FsAction enum for String representation of permissions
69    pub fn get_fs_action(permission: &str) -> Option<FsAction> {
70        FSACTION_VALUES
71            .iter()
72            .filter(|a| a.symbol() == permission)
73            .next()
74            .cloned()
75    }
76}
77
78impl fmt::Display for FsAction {
79    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
80        match self {
81            Self::None => write!(f, "---"),
82            Self::Execute => write!(f, "--x"),
83            Self::Write => write!(f, "-w-"),
84            Self::WriteExecute => write!(f, "-wx"),
85            Self::Read => write!(f, "r--"),
86            Self::ReadExecute => write!(f, "r-x"),
87            Self::ReadWrite => write!(f, "rw-"),
88            Self::All => write!(f, "rwx"),
89        }
90    }
91}
92
93#[cfg(test)]
94mod tests {
95    use super::*;
96
97    #[test]
98    fn test_fs_action() {
99        // implies
100        FsAction::values()
101            .iter()
102            .for_each(|a| assert!(FsAction::All.implies(Some(a))));
103        FsAction::values().iter().for_each(|a| {
104            assert!(if *a == FsAction::None {
105                FsAction::None.implies(Some(a))
106            } else {
107                !FsAction::None.implies(Some(a))
108            });
109        });
110        FsAction::values().iter().for_each(|a| {
111            assert!(if *a == FsAction::ReadExecute
112                || *a == FsAction::Read
113                || *a == FsAction::Execute
114                || *a == FsAction::None
115            {
116                FsAction::ReadExecute.implies(Some(a))
117            } else {
118                !FsAction::ReadExecute.implies(Some(a))
119            });
120        });
121
122        // masks
123        assert!(FsAction::Execute == FsAction::Execute.and(&FsAction::ReadExecute));
124        assert!(FsAction::Read == FsAction::Read.and(&FsAction::ReadExecute));
125        assert!(FsAction::None == FsAction::Write.and(&FsAction::ReadExecute));
126
127        assert!(FsAction::Read == FsAction::ReadExecute.and(&FsAction::ReadWrite));
128        assert!(FsAction::None == FsAction::ReadExecute.and(&FsAction::Write));
129        assert!(FsAction::WriteExecute == FsAction::All.and(&FsAction::WriteExecute));
130    }
131}