use super::{RoleHierarchy, RoleId};
use std::collections::{HashMap, HashSet, VecDeque};
pub type RoleHierarchyMap = HashMap<RoleId, Vec<RoleId>>;
pub fn enumerate_role(role: RoleId, role_hierarchy: &RoleHierarchyMap) -> Vec<RoleId> {
let mut roles = Vec::new();
let mut queue = VecDeque::new();
let mut seen = HashSet::new();
queue.push_back(role);
seen.insert(role);
while let Some(role) = queue.pop_front() {
roles.push(role);
if let Some(children) = role_hierarchy.get(&role) {
for child in children {
if !seen.contains(child) {
queue.push_back(*child);
}
}
}
}
roles
}
pub fn list_role_hierarchy_edges(
role: RoleId,
role_hierarchy: &RoleHierarchyMap,
) -> Vec<RoleHierarchy> {
let mut edges = Vec::new();
let mut roles = Vec::new();
let mut queue = VecDeque::new();
let mut seen = HashSet::new();
queue.push_back(role);
seen.insert(role);
while let Some(role) = queue.pop_front() {
roles.push(role);
if let Some(children) = role_hierarchy.get(&role) {
for child in children {
if !seen.contains(child) {
queue.push_back(*child);
}
edges.push(RoleHierarchy {
super_role_id: role,
role_id: *child,
});
}
}
}
edges
}
#[cfg(test)]
mod test {
use super::*;
#[test]
fn test_enumerate_role() {
let role_hierarchy = [
(RoleId(1), vec![RoleId(2)]),
(RoleId(2), vec![RoleId(3), RoleId(4)]),
(RoleId(4), vec![RoleId(5)]),
(RoleId(6), vec![]),
]
.into_iter()
.collect();
assert_eq!(
enumerate_role(RoleId(1), &role_hierarchy),
[RoleId(1), RoleId(2), RoleId(3), RoleId(4), RoleId(5)]
);
assert_eq!(
enumerate_role(RoleId(2), &role_hierarchy),
[RoleId(2), RoleId(3), RoleId(4), RoleId(5)]
);
assert_eq!(enumerate_role(RoleId(3), &role_hierarchy), [RoleId(3)]);
assert_eq!(
enumerate_role(RoleId(4), &role_hierarchy),
[RoleId(4), RoleId(5)]
);
assert_eq!(enumerate_role(RoleId(5), &role_hierarchy), [RoleId(5)]);
assert_eq!(enumerate_role(RoleId(6), &role_hierarchy), [RoleId(6)]);
assert_eq!(enumerate_role(RoleId(7), &role_hierarchy), [RoleId(7)]);
}
#[test]
fn test_enumerate_role_cyclic() {
let role_hierarchy = [
(RoleId(1), vec![RoleId(2)]),
(RoleId(2), vec![RoleId(3)]),
(RoleId(3), vec![RoleId(1), RoleId(4)]),
]
.into_iter()
.collect();
assert_eq!(
enumerate_role(RoleId(1), &role_hierarchy),
[RoleId(1), RoleId(2), RoleId(3), RoleId(4)]
);
assert_eq!(
enumerate_role(RoleId(2), &role_hierarchy),
[RoleId(2), RoleId(3), RoleId(1), RoleId(4)]
);
assert_eq!(
enumerate_role(RoleId(3), &role_hierarchy),
[RoleId(3), RoleId(1), RoleId(4), RoleId(2)]
);
assert_eq!(enumerate_role(RoleId(4), &role_hierarchy), [RoleId(4)]);
}
}