master
Avril 4 years ago
parent 1cfa16e1f2
commit 4daeea0b4e
Signed by: flanchan
GPG Key ID: 284488987C31F630

@ -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..

@ -341,12 +341,12 @@ impl<T> UnwrapErrInfallible<T> for Result<!, T>
(priv $name:ident $(; $doc:literal)?) => {
$(#[doc=$doc])?
mod $name;
use $name::*;
use self::$name::*;
};
($vis:vis $name:ident $(; $doc:literal)?) => {
$(#[doc=$doc])?
mod $name;
$vis use $name::*;
$vis use self::$name::*;
};
($name:ident $(; $doc:literal)?) => ($crate::submod!(pub $name $(; $doc)?));
}

@ -38,6 +38,7 @@ fn install() -> eyre::Result<()>
Ok(())
}
mod cache;
mod ext;
use ext::*;
mod util;

@ -31,6 +31,7 @@ pub struct User
groups: Vec<GroupID>,
}
submod!(user; "impls for `User`.");
//TODO: Iterator over all `Group`s a user is a part of (i.e. each group they're in's deduped & flattened inheritance graph)

@ -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>{}

@ -12,3 +12,9 @@ pub fn jitter<T>(min: T, max: T) -> T
thread.sample(dist)
}
/// Compare pointer identity
#[inline(always)] pub fn ptr_eq<T>(ptr: &T, other: &T) -> bool
{
ptr as *const T as usize ==
other as *const T as usize
}

Loading…
Cancel
Save