use crate::model::*;
use std::collections::HashMap;
#[allow(unused_variables)]
pub trait PolicyVisitor {
fn start(&mut self) {}
fn id(&mut self, i: &str) {}
fn version(&mut self, v: &Version) {}
fn statement_visitor(&mut self) -> Option<Box<&mut dyn StatementVisitor>> {
None
}
fn finish(&mut self) {}
}
#[allow(unused_variables)]
pub trait StatementVisitor {
fn start(&mut self) {}
fn sid(&mut self, s: &str) {}
fn effect(&mut self, e: &Effect) {}
fn principal(&mut self, p: &Principal) {}
fn action(&mut self, a: &Action) {}
fn resource(&mut self, r: &Resource) {}
fn condition_visitor(&mut self) -> Option<Box<&mut dyn ConditionVisitor>> {
None
}
fn finish(&mut self) {}
}
#[allow(unused_variables)]
pub trait ConditionVisitor {
fn start(&mut self) {}
fn left(&mut self, f: &QString, op: &ConditionOperator) {}
fn operator(&mut self, op: &ConditionOperator) {}
fn right(&mut self, v: &OneOrAll<ConditionValue>, op: &ConditionOperator) {}
fn finish(&mut self) {}
}
pub fn walk_policy(policy: &Policy, visitor: &mut impl PolicyVisitor) {
visitor.start();
if let Some(id) = &policy.id {
visitor.id(id);
}
if let Some(version) = &policy.version {
visitor.version(version);
}
if let Some(statement_visitor) = visitor.statement_visitor() {
match &policy.statement {
OneOrAll::One(statement) => walk_statement(statement, statement_visitor),
OneOrAll::All(statements) => {
for statement in statements {
walk_statement(statement, visitor.statement_visitor().unwrap())
}
}
}
}
visitor.finish();
}
fn walk_statement(statement: &Statement, visitor: Box<&mut dyn StatementVisitor>) {
visitor.start();
if let Some(sid) = &statement.sid {
visitor.sid(sid);
}
visitor.effect(&statement.effect);
if let Some(principal) = &statement.principal {
visitor.principal(principal);
}
visitor.action(&statement.action);
visitor.resource(&statement.resource);
if let Some(conditions) = &statement.condition {
if let Some(condition_visitor) = visitor.condition_visitor() {
walk_conditions(conditions, condition_visitor)
}
}
visitor.finish();
}
fn walk_conditions(
conditions: &HashMap<ConditionOperator, HashMap<QString, OneOrAll<ConditionValue>>>,
visitor: Box<&mut dyn ConditionVisitor>,
) {
for (op, rhs) in conditions {
for (field, values) in rhs {
visitor.start();
visitor.left(field, op);
visitor.operator(op);
visitor.right(values, op);
visitor.finish();
}
}
}