use std::collections::BTreeMap;
use std::sync::{Arc, Weak};
use itertools::Itertools;
use derive_more::Display;
use crate::Extension;
use crate::extension::{ExtensionId, ExtensionRegistry};
#[derive(Debug, Display, Default, Clone)]
#[display("WeakExtensionRegistry[{}]", exts.keys().join(", "))]
pub struct WeakExtensionRegistry {
exts: BTreeMap<ExtensionId, Weak<Extension>>,
}
impl WeakExtensionRegistry {
pub fn new(extensions: impl IntoIterator<Item = (ExtensionId, Weak<Extension>)>) -> Self {
let mut res = Self::default();
for (id, ext) in extensions {
res.register(id, ext);
}
res
}
#[must_use]
pub fn get(&self, name: &str) -> Option<&Weak<Extension>> {
self.exts.get(name)
}
#[must_use]
pub fn contains(&self, name: &str) -> bool {
self.exts.contains_key(name)
}
pub fn register(&mut self, id: ExtensionId, ext: impl Into<Weak<Extension>>) -> bool {
self.exts.insert(id, ext.into()).is_none()
}
pub fn iter(&self) -> impl Iterator<Item = (&ExtensionId, &Weak<Extension>)> {
self.exts.iter()
}
pub fn extensions(&self) -> impl Iterator<Item = &Weak<Extension>> {
self.exts.values()
}
pub fn ids(&self) -> impl Iterator<Item = &ExtensionId> {
self.exts.keys()
}
}
impl IntoIterator for WeakExtensionRegistry {
type Item = Weak<Extension>;
type IntoIter = std::collections::btree_map::IntoValues<ExtensionId, Weak<Extension>>;
fn into_iter(self) -> Self::IntoIter {
self.exts.into_values()
}
}
impl<'a> TryFrom<&'a WeakExtensionRegistry> for ExtensionRegistry {
type Error = ();
fn try_from(weak: &'a WeakExtensionRegistry) -> Result<Self, Self::Error> {
let exts: Vec<Arc<Extension>> = weak
.extensions()
.map(|w| w.upgrade().ok_or(()))
.try_collect()?;
Ok(ExtensionRegistry::new(exts))
}
}
impl TryFrom<WeakExtensionRegistry> for ExtensionRegistry {
type Error = ();
fn try_from(weak: WeakExtensionRegistry) -> Result<Self, Self::Error> {
let exts: Vec<Arc<Extension>> = weak
.into_iter()
.map(|w| w.upgrade().ok_or(()))
.try_collect()?;
Ok(ExtensionRegistry::new(exts))
}
}
impl<'a> From<&'a ExtensionRegistry> for WeakExtensionRegistry {
fn from(reg: &'a ExtensionRegistry) -> Self {
let exts = reg
.iter()
.map(|ext| (ext.name().clone(), Arc::downgrade(ext)))
.collect();
Self { exts }
}
}