#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Grant<T> {
project: Option<T>,
user: Option<T>,
default: T,
}
impl<T: Ord + Copy> Grant<T> {
#[must_use]
pub fn from_layers(project: Option<T>, user: Option<T>, default: T) -> Self {
Self {
project,
user,
default,
}
}
fn baseline(self) -> T {
self.user.unwrap_or(self.default)
}
#[must_use]
pub fn as_effective(self) -> Option<T> {
match self.project {
Some(p) if p <= self.baseline() => Some(p),
_ => self.user,
}
}
#[must_use]
pub fn resolved(self) -> T {
self.as_effective().unwrap_or(self.default)
}
#[must_use]
pub fn project_widening_ignored(self) -> bool {
matches!(self.project, Some(p) if p > self.baseline())
}
#[must_use]
pub fn project_narrowed(self) -> bool {
matches!(self.project, Some(p) if p < self.baseline())
}
}
#[cfg(test)]
mod tests {
use super::Grant;
#[test]
fn a_switch_denies_from_the_project_and_grants_only_from_the_user() {
let g = |project, user| Grant::from_layers(project, user, false);
assert_eq!(g(Some(false), None).as_effective(), Some(false));
assert_eq!(g(Some(false), Some(true)).as_effective(), Some(false));
assert!(g(Some(false), Some(true)).project_narrowed());
assert_eq!(g(Some(true), None).as_effective(), None);
assert!(g(Some(true), None).project_widening_ignored());
assert_eq!(g(None, None).as_effective(), None);
assert_eq!(g(None, Some(true)).as_effective(), Some(true));
}
#[test]
fn a_bound_may_be_lowered_by_the_project_and_raised_only_by_the_user() {
let g = |project, user| Grant::from_layers(project, user, 32_768_usize);
assert_eq!(g(None, Some(131_072)).resolved(), 131_072);
assert_eq!(g(Some(131_072), None).resolved(), 32_768);
assert!(g(Some(131_072), None).project_widening_ignored());
assert_eq!(g(Some(16_384), None).resolved(), 16_384);
assert_eq!(g(Some(65_536), Some(131_072)).resolved(), 65_536);
assert!(g(Some(65_536), Some(131_072)).project_narrowed());
assert_eq!(g(None, None).as_effective(), None);
assert_eq!(g(None, None).resolved(), 32_768);
}
#[test]
fn a_project_restating_the_baseline_is_not_an_ignored_grant() {
let at_default = Grant::from_layers(Some(32_768_usize), None, 32_768);
assert_eq!(at_default.as_effective(), Some(32_768));
assert!(!at_default.project_widening_ignored());
assert!(!at_default.project_narrowed());
}
}