use serde::{Deserialize, Serialize};
use std::fmt;
#[derive(
Debug, Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Serialize, Deserialize, Default,
)]
#[repr(u8)]
pub enum PermissionLevel {
#[default]
None = 0,
Read = 1,
Write = 2,
Execute = 3,
Admin = 4,
}
impl PermissionLevel {
pub fn as_u8(self) -> u8 {
self as u8
}
pub fn from_u8(value: u8) -> Option<Self> {
match value {
0 => Some(Self::None),
1 => Some(Self::Read),
2 => Some(Self::Write),
3 => Some(Self::Execute),
4 => Some(Self::Admin),
_ => None,
}
}
pub fn satisfies(self, required: Self) -> bool {
self >= required
}
pub fn implied_levels(self) -> Vec<Self> {
match self {
Self::None => vec![Self::None],
Self::Read => vec![Self::None, Self::Read],
Self::Write => vec![Self::None, Self::Read, Self::Write],
Self::Execute => vec![Self::None, Self::Read, Self::Write, Self::Execute],
Self::Admin => vec![
Self::None,
Self::Read,
Self::Write,
Self::Execute,
Self::Admin,
],
}
}
pub fn all() -> &'static [Self] {
&[
Self::None,
Self::Read,
Self::Write,
Self::Execute,
Self::Admin,
]
}
}
impl fmt::Display for PermissionLevel {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
Self::None => write!(f, "None"),
Self::Read => write!(f, "Read"),
Self::Write => write!(f, "Write"),
Self::Execute => write!(f, "Execute"),
Self::Admin => write!(f, "Admin"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_level_ordering() {
assert!(PermissionLevel::Admin > PermissionLevel::Execute);
assert!(PermissionLevel::Execute > PermissionLevel::Write);
assert!(PermissionLevel::Write > PermissionLevel::Read);
assert!(PermissionLevel::Read > PermissionLevel::None);
}
#[test]
fn test_satisfies() {
assert!(PermissionLevel::Read.satisfies(PermissionLevel::Read));
assert!(PermissionLevel::Write.satisfies(PermissionLevel::Write));
assert!(PermissionLevel::Write.satisfies(PermissionLevel::Read));
assert!(PermissionLevel::Execute.satisfies(PermissionLevel::Write));
assert!(PermissionLevel::Admin.satisfies(PermissionLevel::Execute));
assert!(PermissionLevel::Admin.satisfies(PermissionLevel::None));
assert!(PermissionLevel::Admin.satisfies(PermissionLevel::Read));
assert!(PermissionLevel::Admin.satisfies(PermissionLevel::Write));
assert!(PermissionLevel::Admin.satisfies(PermissionLevel::Execute));
assert!(PermissionLevel::Admin.satisfies(PermissionLevel::Admin));
assert!(!PermissionLevel::Read.satisfies(PermissionLevel::Write));
assert!(!PermissionLevel::Write.satisfies(PermissionLevel::Execute));
assert!(!PermissionLevel::Execute.satisfies(PermissionLevel::Admin));
assert!(!PermissionLevel::None.satisfies(PermissionLevel::Read));
}
#[test]
fn test_from_u8() {
assert_eq!(PermissionLevel::from_u8(0), Some(PermissionLevel::None));
assert_eq!(PermissionLevel::from_u8(1), Some(PermissionLevel::Read));
assert_eq!(PermissionLevel::from_u8(2), Some(PermissionLevel::Write));
assert_eq!(PermissionLevel::from_u8(3), Some(PermissionLevel::Execute));
assert_eq!(PermissionLevel::from_u8(4), Some(PermissionLevel::Admin));
assert_eq!(PermissionLevel::from_u8(5), None);
}
#[test]
fn test_implied_levels() {
assert_eq!(
PermissionLevel::Write.implied_levels(),
vec![
PermissionLevel::None,
PermissionLevel::Read,
PermissionLevel::Write
]
);
}
#[test]
fn test_display() {
assert_eq!(format!("{}", PermissionLevel::Read), "Read");
assert_eq!(format!("{}", PermissionLevel::Admin), "Admin");
}
#[test]
fn test_serialization() {
let level = PermissionLevel::Write;
let json = serde_json::to_string(&level).unwrap();
assert_eq!(json, "\"Write\"");
let deserialized: PermissionLevel = serde_json::from_str(&json).unwrap();
assert_eq!(deserialized, level);
}
}