use std::convert::TryFrom;
use std::ops::BitOr;
use super::Cap;
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub struct Set(u64);
impl Set {
pub fn empty() -> Self {
Self(0)
}
pub fn clear(&mut self) {
self.0 = 0;
}
pub fn contains<S: Into<Set>>(&self, set: S) -> bool {
self.0 & set.into().0 != 0
}
pub fn insert<S: Into<Set>>(&mut self, set: S) {
self.0 |= set.into().0
}
pub fn remove<S: Into<Set>>(&mut self, set: S) {
self.0 &= !set.into().0;
}
pub fn shift(&self, high: &mut u32, low: &mut u32) {
const MASK: u64 = 0xFFFFFFFF;
*high = u32::try_from(self.0 >> 32 & MASK).unwrap_or(0);
*low = u32::try_from(self.0 & MASK).unwrap_or(0);
}
}
impl BitOr for Cap {
type Output = Set;
fn bitor(self, rhs: Self) -> Set {
let x = u64::from(self);
let y = u64::from(rhs);
Set(x | y)
}
}
impl BitOr<Cap> for Set {
type Output = Set;
fn bitor(self, rhs: Cap) -> Set {
let x = self.0;
let y = u64::from(rhs);
Self(x | y)
}
}
impl From<Cap> for Set {
fn from(cap: Cap) -> Self {
Self(u64::from(cap))
}
}
impl From<(u32, u32)> for Set {
fn from((high, low): (u32, u32)) -> Self {
let x = u64::from(high) << 32;
let y = u64::from(low);
Self(x | y)
}
}
#[test]
fn test() {
use crate::caps::*;
let mut set = Set::empty();
set.insert(Chown);
set.insert(Lease | Mknod);
assert!(set.contains(Chown));
assert!(set.contains(Chown | Lease | Mknod));
assert!(!set.contains(Syslog));
set.remove(Lease);
assert!(!set.contains(Lease));
assert!(set.contains(Chown | Mknod));
set.clear();
assert_eq!(Set::empty(), set);
}