use crate::{db_pools::DbPools, provider::PoolProvider};
use std::{collections::HashMap, error::Error, fmt};
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct UnknownPool {
name: String,
}
impl UnknownPool {
fn new(name: &str) -> Self {
Self {
name: name.to_owned(),
}
}
pub fn name(&self) -> &str {
&self.name
}
}
impl fmt::Display for UnknownPool {
fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
write!(formatter, "unknown pool `{}`", self.name)
}
}
impl Error for UnknownPool {}
#[derive(Clone, Debug)]
pub struct PoolRegistry<P: PoolProvider = DbPools> {
pools: HashMap<String, P>,
}
impl<P: PoolProvider> PoolRegistry<P> {
pub fn new() -> Self {
Self {
pools: HashMap::new(),
}
}
pub fn insert(&mut self, name: impl Into<String>, provider: P) -> Option<P> {
self.pools.insert(name.into(), provider)
}
pub fn get(&self, name: &str) -> Option<&P> {
self.pools.get(name)
}
pub fn try_get(&self, name: &str) -> Result<&P, UnknownPool> {
self.get(name).ok_or_else(|| UnknownPool::new(name))
}
pub fn contains_key(&self, name: &str) -> bool {
self.pools.contains_key(name)
}
pub fn len(&self) -> usize {
self.pools.len()
}
pub fn is_empty(&self) -> bool {
self.pools.is_empty()
}
pub fn iter(&self) -> impl Iterator<Item = (&str, &P)> {
self.pools
.iter()
.map(|(name, provider)| (name.as_str(), provider))
}
}
impl<P: PoolProvider> Default for PoolRegistry<P> {
fn default() -> Self {
Self::new()
}
}
impl<K, P> FromIterator<(K, P)> for PoolRegistry<P>
where
K: Into<String>,
P: PoolProvider,
{
fn from_iter<T: IntoIterator<Item = (K, P)>>(iter: T) -> Self {
let mut registry = Self::new();
registry.extend(iter);
registry
}
}
impl<K, P> Extend<(K, P)> for PoolRegistry<P>
where
K: Into<String>,
P: PoolProvider,
{
fn extend<T: IntoIterator<Item = (K, P)>>(&mut self, iter: T) {
self.pools.extend(
iter.into_iter()
.map(|(name, provider)| (name.into(), provider)),
);
}
}