pub mod types;
use std::collections::HashMap;
use std::sync::Arc;
pub use types::{AuthorshipMode, PersonaExpansion, PersonaParams, ReviewSpec, TriggerSpec};
use crate::error::Error;
pub trait Persona: Send + Sync {
fn name(&self) -> &str;
fn description(&self) -> &str;
fn version(&self) -> &str;
fn expand(&self, params: &PersonaParams) -> Result<PersonaExpansion, Error>;
}
pub struct PersonaRegistry {
personas: HashMap<String, Arc<dyn Persona>>,
}
impl Default for PersonaRegistry {
fn default() -> Self {
Self::new()
}
}
impl PersonaRegistry {
pub fn new() -> Self {
Self {
personas: HashMap::new(),
}
}
pub fn register(&mut self, persona: Arc<dyn Persona>) {
self.personas.insert(persona.name().to_string(), persona);
}
pub fn get(&self, name: &str) -> Option<Arc<dyn Persona>> {
self.personas.get(name).cloned()
}
pub fn list(&self) -> Vec<&str> {
self.personas.keys().map(|k| k.as_str()).collect()
}
pub fn len(&self) -> usize {
self.personas.len()
}
pub fn is_empty(&self) -> bool {
self.personas.is_empty()
}
}
#[cfg(test)]
mod tests {
use super::*;
struct DummyPersona;
impl Persona for DummyPersona {
fn name(&self) -> &str {
"dummy:p"
}
fn description(&self) -> &str {
"test persona"
}
fn version(&self) -> &str {
"0.1.0"
}
fn expand(&self, _params: &PersonaParams) -> Result<PersonaExpansion, Error> {
Ok(PersonaExpansion::default())
}
}
#[test]
fn registry_starts_empty() {
let r = PersonaRegistry::new();
assert!(r.is_empty());
assert_eq!(r.len(), 0);
assert!(r.list().is_empty());
assert!(r.get("anything").is_none());
}
#[test]
fn register_and_get_round_trip() {
let mut r = PersonaRegistry::new();
r.register(Arc::new(DummyPersona));
assert_eq!(r.len(), 1);
assert!(r.get("dummy:p").is_some());
assert_eq!(r.list(), vec!["dummy:p"]);
}
#[test]
fn register_same_name_replaces() {
let mut r = PersonaRegistry::new();
r.register(Arc::new(DummyPersona));
r.register(Arc::new(DummyPersona));
assert_eq!(r.len(), 1);
}
}