use std::collections::HashMap;
use std::fmt;
use crate::agent::AgentDescriptor;
use crate::claims::GlobalClaimList;
use crate::error::Error;
use crate::protocol::ProtocolBehavior;
use crate::put::{Put, PutOptions};
pub const TCP_PUT: &str = "tcp";
pub struct PutRegistry<PB> {
factories: HashMap<String, Box<dyn Factory<PB>>>,
default_put: String,
}
impl<PB: ProtocolBehavior> PartialEq for PutRegistry<PB> {
fn eq(&self, other: &Self) -> bool {
self.default_put == other.default_put
&& self.factories.len() == other.factories.len()
&& self
.factories
.keys()
.all(|id| other.factories.contains_key(id))
}
}
impl<PB: ProtocolBehavior> fmt::Debug for PutRegistry<PB> {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("PutRegistry (default only)")
.field("default", &self.default().name())
.finish()
}
}
impl<PB: ProtocolBehavior> PutRegistry<PB> {
pub fn new<SI, I, S>(puts: I, default: S) -> Self
where
SI: Into<String>,
I: IntoIterator<Item = (SI, Box<dyn Factory<PB>>)>,
S: Into<String>,
{
let result = Self {
factories: puts
.into_iter()
.map(|(id, f)| (Into::<String>::into(id), f))
.collect(),
default_put: default.into(),
};
let _ = result.find_by_id(&result.default_put);
result
}
pub fn default(&self) -> &dyn Factory<PB> {
self.find_by_id(&self.default_put)
.unwrap_or_else(|| panic!("default PUT {} is not in registry", &self.default_put))
}
pub fn puts(&self) -> impl Iterator<Item = (&str, &dyn Factory<PB>)> {
self.factories
.iter()
.map(|(n, f)| (n.as_str(), f.to_owned().as_ref()))
}
pub fn find_by_id<S: AsRef<str>>(&self, id: S) -> Option<&dyn Factory<PB>> {
self.factories
.get(id.as_ref())
.map(|f| f.to_owned().as_ref())
}
pub fn determinism_reseed_all_factories(&self) {
log::debug!("[RNG] reseed all PUT factories");
for (_, factory) in self.factories.iter() {
factory.rng_reseed();
}
}
}
impl<PB: ProtocolBehavior> Clone for PutRegistry<PB> {
fn clone(&self) -> Self {
Self::new(
self.factories
.iter()
.map(|(n, f)| (n.clone(), f.clone_factory())),
self.default_put.clone(),
)
}
}
#[derive(Debug)]
pub enum PutKind {
CPUT,
Rust,
}
pub trait Factory<PB: ProtocolBehavior> {
fn create(
&self,
agent_descriptor: &AgentDescriptor,
claims: &GlobalClaimList<PB::ProtocolTypes, PB::Claim>,
options: &PutOptions,
) -> Result<Box<dyn Put<PB>>, Error>;
fn kind(&self) -> PutKind;
fn name(&self) -> String;
fn versions(&self) -> Vec<(String, String)>;
fn clone_factory(&self) -> Box<dyn Factory<PB>>;
fn rng_reseed(&self) {
log::debug!("[RNG] reseed failed ({}): not supported", self.name());
}
}