parent
b097c3b5ae
commit
d3c644836a
@ -0,0 +1,126 @@
|
|||||||
|
//! Group specific impls
|
||||||
|
use super::*;
|
||||||
|
use std::collections::{
|
||||||
|
VecDeque,
|
||||||
|
HashSet, hash_set,
|
||||||
|
};
|
||||||
|
|
||||||
|
impl Group
|
||||||
|
{
|
||||||
|
/// Is this group hidden from searches?
|
||||||
|
#[inline(always)] pub fn is_hidden(&self) -> bool
|
||||||
|
{
|
||||||
|
self.hidden
|
||||||
|
}
|
||||||
|
/// Set if this group should be hidden from searches.
|
||||||
|
#[inline(always)] pub fn set_hidden(&mut self, hide: bool)
|
||||||
|
{
|
||||||
|
self.hidden = hide;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// The flattened inheritance graph of this `Group` within this `Userspace`.
|
||||||
|
pub fn inherits_from<'g, 'u>(&'g self, space: &'u Userspace) -> GroupInheritanceIter<'u>
|
||||||
|
where 'g: 'u
|
||||||
|
{
|
||||||
|
GroupInheritanceIter {
|
||||||
|
group: self,
|
||||||
|
space,
|
||||||
|
|
||||||
|
level: self.inherits.clone().unwrap_or_default().into(),
|
||||||
|
done: HashSet::new(),
|
||||||
|
|
||||||
|
is_cyclic: false,
|
||||||
|
|
||||||
|
cyclic_refs: Default::default(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// An iterator over a `Group`'s entire inheritance graph.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct GroupInheritanceIter<'u>
|
||||||
|
{
|
||||||
|
group: &'u Group,
|
||||||
|
space: &'u Userspace,
|
||||||
|
|
||||||
|
level: VecDeque<GroupID>,
|
||||||
|
|
||||||
|
done: HashSet<GroupID>,
|
||||||
|
|
||||||
|
is_cyclic: bool,
|
||||||
|
|
||||||
|
cyclic_refs: HashSet<&'u GroupID>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> GroupInheritanceIter<'a>
|
||||||
|
{
|
||||||
|
/// The group this iterator is working for
|
||||||
|
#[inline] pub fn base_group(&self) -> &Group
|
||||||
|
{
|
||||||
|
self.group
|
||||||
|
}
|
||||||
|
/// The userspace this iterator is searching in
|
||||||
|
#[inline] pub fn userspace(&self) -> &Userspace
|
||||||
|
{
|
||||||
|
self.space
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Does this inheritance graph contain cyclic references so far?
|
||||||
|
#[inline] pub fn contains_cyclic_references(&self) -> bool
|
||||||
|
{
|
||||||
|
self.is_cyclic
|
||||||
|
}
|
||||||
|
/// The cyclic references found by this iterator so far (if any).
|
||||||
|
#[inline] pub fn cyclic_refs(&self) -> hash_set::Iter<'_, &'a GroupID>
|
||||||
|
{
|
||||||
|
self.cyclic_refs.iter()
|
||||||
|
}
|
||||||
|
/// All group IDs that have been processed by the iterator so far
|
||||||
|
#[inline] pub fn processed_group_ids(&self) -> hash_set::Iter<'_, GroupID>
|
||||||
|
{
|
||||||
|
self.done.iter()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'u> Iterator for GroupInheritanceIter<'u>
|
||||||
|
{
|
||||||
|
type Item = &'u Group;
|
||||||
|
fn next(&mut self) -> Option<Self::Item>
|
||||||
|
{
|
||||||
|
match self.level
|
||||||
|
.pop_front()
|
||||||
|
.map(|id| (self.space.groups.get(&id),
|
||||||
|
self.done.insert(id)))
|
||||||
|
{
|
||||||
|
#[cold] Some((None, _)) => panic!("Group inheritance graph for group ID {:?} contained invalid ID not found within this userspace", self.group.id),
|
||||||
|
Some((Some(group), false)) => {
|
||||||
|
// We've already processed this ID, it is a cyclic reference.
|
||||||
|
// Ignore it and continue
|
||||||
|
if cfg!(debug_assertions) && !self.is_cyclic {
|
||||||
|
warn!("Cyclic reference found for group ID {:?} while calculating the inheritance graph of group {:?}", group.id, self.group.id);
|
||||||
|
}
|
||||||
|
self.is_cyclic = true;
|
||||||
|
self.cyclic_refs.insert(&group.id);
|
||||||
|
self.next()
|
||||||
|
},
|
||||||
|
Some((Some(group), _)) => {
|
||||||
|
if let Some(high) = &group.inherits {
|
||||||
|
self.level.reserve(high.len());
|
||||||
|
for high in high.iter().cloned().rev() {
|
||||||
|
self.level.push_front(high);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Some(group)
|
||||||
|
},
|
||||||
|
_ => None,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
fn size_hint(&self) -> (usize, Option<usize>) {
|
||||||
|
match self.level.len() {
|
||||||
|
0 => (0, Some(0)),
|
||||||
|
n => (n, None),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<'a> std::iter::FusedIterator for GroupInheritanceIter<'a>{}
|
||||||
|
|
Loading…
Reference in new issue