use std::collections::{HashMap, HashSet};
use agent_contracts::hook::{Hooker, HookerRegistry};
use agent_types::common::HookerId;
use agent_types::hook::HookPointId;
pub struct HookerRegistryImpl {
hookers: HashMap<HookerId, Box<dyn Hooker>>,
enabled_hookers: HashSet<HookerId>,
policies: HashMap<HookerId, serde_json::Value>,
}
impl HookerRegistryImpl {
pub fn new(
hookers: HashMap<HookerId, Box<dyn Hooker>>,
enabled_hookers: HashSet<HookerId>,
policies: HashMap<HookerId, serde_json::Value>,
) -> Self {
Self {
hookers,
enabled_hookers,
policies,
}
}
fn hook_point_matches(pattern: &str, candidate: &str) -> bool {
let pattern_segments: Vec<_> = pattern.split('.').collect();
let candidate_segments: Vec<_> = candidate.split('.').collect();
pattern_segments.len() == candidate_segments.len()
&& pattern_segments.iter().zip(candidate_segments.iter()).all(
|(pattern_segment, candidate_segment)| {
pattern_segment == candidate_segment || *pattern_segment == "*"
},
)
}
}
impl HookerRegistry for HookerRegistryImpl {
fn get(&self, id: &HookerId) -> Option<&dyn Hooker> {
self.hookers.get(id).map(Box::as_ref)
}
fn list(&self) -> Vec<&dyn Hooker> {
self.hookers.values().map(Box::as_ref).collect()
}
fn list_for_hook_point(&self, hook_point: &HookPointId) -> Vec<&dyn Hooker> {
self.hookers
.values()
.filter(|hooker| Self::hook_point_matches(&hooker.hook_point().0, &hook_point.0))
.map(Box::as_ref)
.collect()
}
fn is_enabled(&self, id: &HookerId) -> bool {
self.enabled_hookers.contains(id)
}
fn policy_for(&self, id: &HookerId) -> Option<&serde_json::Value> {
self.policies.get(id)
}
}