use std::{cmp::Ordering, sync::Arc, time::SystemTime};
use sciparse::path::ScionPath;
use crate::path::{policy::PathPolicy, scoring::PathScorer, types::PathManagerPath};
pub mod policy;
pub(crate) mod scoring;
#[derive(Default)]
pub struct PathStrategy {
pub policies: Vec<Arc<dyn PathPolicy>>,
pub(crate) scoring: PathScorer,
}
impl PathStrategy {
pub fn add_policy(&mut self, policy: impl PathPolicy) {
self.policies.push(Arc::new(policy));
}
#[cfg(test)]
pub(crate) fn add_scoring(
&mut self,
scoring: impl crate::path::scoring::PathScoring,
impact: f32,
) {
self.scoring = std::mem::take(&mut self.scoring).with_scorer(scoring, impact);
}
pub(crate) fn rank_order(
&self,
this: &PathManagerPath,
other: &PathManagerPath,
now: SystemTime,
) -> Ordering {
let this_score = self.scoring.score(this, now);
let other_score = self.scoring.score(other, now);
this_score.total_cmp(&other_score).reverse() }
pub(crate) fn rank_inplace(&self, path: &mut [PathManagerPath], now: SystemTime) {
path.sort_by(|a, b| self.rank_order(a, b, now));
}
pub fn predicate(&self, path: &ScionPath) -> bool {
self.policies.iter().all(|policy| policy.predicate(path))
}
pub fn filter_inplace(&self, paths: &mut Vec<ScionPath>) {
paths.retain(|p| self.predicate(p));
}
}