parent
1cfa16e1f2
commit
4daeea0b4e
@ -0,0 +1,84 @@
|
|||||||
|
//! Caching utilities
|
||||||
|
use std::mem::{self, MaybeUninit};
|
||||||
|
use std::error;
|
||||||
|
use std::borrow::Borrow;
|
||||||
|
use std::sync::RwLock;
|
||||||
|
|
||||||
|
/// A trait for objects that can cache an operation in themselves
|
||||||
|
pub trait Cache
|
||||||
|
{
|
||||||
|
type Cached;
|
||||||
|
|
||||||
|
/// Compute the `Cached` value.
|
||||||
|
fn cache(&self) -> Self::Cached;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// A value that might be cached or not.
|
||||||
|
#[derive(Debug, Clone, PartialEq, Eq, Hash, Ord, PartialOrd)]
|
||||||
|
pub enum MaybeCached<T: Cache>
|
||||||
|
{
|
||||||
|
Uncached(T),
|
||||||
|
Cached(T::Cached),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T: Cache> MaybeCached<T>
|
||||||
|
{
|
||||||
|
/// Cache the operation
|
||||||
|
#[inline] pub fn cache(&mut self)
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Self::Uncached(val) => *self = Self::Cached(val.cache()),
|
||||||
|
_ => (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Has this value been cached
|
||||||
|
pub fn is_cached(&self) -> bool
|
||||||
|
{
|
||||||
|
if let Self::Cached(_) = &self {
|
||||||
|
true
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Consume into the cached operation
|
||||||
|
#[inline] pub fn into_cached(mut self) -> Self
|
||||||
|
{
|
||||||
|
self.cache();
|
||||||
|
self
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Compute the operation
|
||||||
|
#[inline] pub fn compute(self) -> T::Cached
|
||||||
|
{
|
||||||
|
match self {
|
||||||
|
Self::Cached(c) => c,
|
||||||
|
Self::Uncached(val) => val.cache(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F, T> Cache for F
|
||||||
|
where F: Fn() -> T
|
||||||
|
{
|
||||||
|
type Cached = T;
|
||||||
|
#[inline] fn cache(&self) -> Self::Cached
|
||||||
|
{
|
||||||
|
self()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
#[derive(Debug)]
|
||||||
|
pub struct LazyCached<T: Cache + ?Sized>(RwLock<Option<T::Cached>>, T);
|
||||||
|
|
||||||
|
impl<T: Cache> LazyCached<T>
|
||||||
|
{
|
||||||
|
pub fn new(value: T) -> Self
|
||||||
|
{
|
||||||
|
Self(RwLock::new(None), value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
//TODO:idfk..
|
@ -0,0 +1,113 @@
|
|||||||
|
//! impls for `User`
|
||||||
|
use super::*;
|
||||||
|
use std::borrow::Cow;
|
||||||
|
use std::iter;
|
||||||
|
|
||||||
|
/// A container of `Group` references in a `Userspace` from `GroupID`s
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct Groups<'u>(usize, Cow<'u, [GroupID]>, &'u Userspace);
|
||||||
|
/// An iterator over all groups a user is a part of.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct AllGroups<'u>(Vec<(Option<&'u Group>, GroupInheritanceIter<'u>)>);
|
||||||
|
|
||||||
|
impl User
|
||||||
|
{
|
||||||
|
/// All groups the user is explicitly a part of
|
||||||
|
pub fn groups_explicit<'a, 'u>(&'a self, space: &'u Userspace) -> Groups<'u>
|
||||||
|
where 'a: 'u
|
||||||
|
{
|
||||||
|
Groups(0, Cow::Borrowed(&self.groups[..]), space)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// All groups the user is a part of, including inherited groups and implcit (todo) ones
|
||||||
|
pub fn all_groups<'a, 'u>(&'a self, space: &'u Userspace) -> AllGroups<'u>
|
||||||
|
where 'a: 'u
|
||||||
|
{
|
||||||
|
AllGroups(self.groups_explicit(space).map(|group| (Some(group), group.inherits_from(space))).rev().collect())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'u> Groups<'u>
|
||||||
|
{
|
||||||
|
/// The group IDs remaining in this iterator.
|
||||||
|
pub fn ids(&self) -> &[GroupID]
|
||||||
|
{
|
||||||
|
&self.1[self.0..]
|
||||||
|
}
|
||||||
|
/// The userspace for this iterator.
|
||||||
|
pub fn space(&self) -> &Userspace
|
||||||
|
{
|
||||||
|
&self.2
|
||||||
|
}
|
||||||
|
/// Copy as a reference with a lower lifetime.
|
||||||
|
pub fn copied<'a>(&'a self) -> Groups<'a>
|
||||||
|
{
|
||||||
|
Groups(self.0, Cow::Borrowed(&self.1[..]), self.2)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'u> Iterator for Groups<'u>
|
||||||
|
{
|
||||||
|
type Item = &'u Group;
|
||||||
|
fn next(&mut self) -> Option<Self::Item>
|
||||||
|
{
|
||||||
|
(if self.0>=self.1.len() {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
Some(self.2.groups.get(&self.1[self.0]).expect("Groups contained invalid group ID for its userspace"))
|
||||||
|
}, self.0+=1).0
|
||||||
|
}
|
||||||
|
#[inline] fn nth(&mut self, n: usize) -> Option<Self::Item>
|
||||||
|
{
|
||||||
|
if (..self.len()).contains(&n) {
|
||||||
|
Some(self.2.groups.get(&self.1[n]).expect("Groups contained invalid group ID for its userspace"))
|
||||||
|
} else {
|
||||||
|
None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
let v = self.1.len() - self.0;
|
||||||
|
(v, Some(v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'u> iter::DoubleEndedIterator for Groups<'u>
|
||||||
|
{
|
||||||
|
fn next_back(&mut self) -> Option<Self::Item>
|
||||||
|
{
|
||||||
|
if self.0 == 0 {
|
||||||
|
None
|
||||||
|
} else {
|
||||||
|
self.0-=1;
|
||||||
|
debug_assert!(self.0<self.1.len(), "bad DEI impl");
|
||||||
|
Some(self.2.groups.get(&self.1[self.0]).expect("Groups contained invalid group ID for its userspace"))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'u> iter::ExactSizeIterator for Groups<'u>{}
|
||||||
|
impl<'u> iter::FusedIterator for Groups<'u>{}
|
||||||
|
|
||||||
|
impl<'u> Iterator for AllGroups<'u>
|
||||||
|
{
|
||||||
|
type Item = &'u Group;
|
||||||
|
fn next(&mut self) -> Option<Self::Item>
|
||||||
|
{
|
||||||
|
match self.0.last_mut()
|
||||||
|
{
|
||||||
|
Some((mut v @ Some(_), _)) => v.take(),
|
||||||
|
Some((None, iter)) => {
|
||||||
|
if let Some(igroup) = iter.next() {
|
||||||
|
Some(igroup)
|
||||||
|
} else {
|
||||||
|
self.0.pop();
|
||||||
|
self.next()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
_ => None
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
(self.0.iter().map(|(g, i)| (g.is_some() as usize) + i.size_hint().0).sum(), None)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'u> iter::FusedIterator for AllGroups<'u>{}
|
Loading…
Reference in new issue