1use super::{Backend, BoxedBackend, BoxedConnector};
2use crate::{Error, Result, ToUrl};
3use log::{error, info};
4use std::sync::{Arc, RwLock};
5
6type Backends = Arc<RwLock<Vec<BoxedBackend>>>;
8
9#[derive(Clone)]
13pub struct Manager {
14 backends: Backends,
15}
16
17impl Default for Manager {
18 fn default() -> Self {
20 Self {
21 backends: Arc::new(RwLock::new(Vec::default())),
22 }
23 }
24}
25
26impl Manager {
27 pub fn register(&self, backend: impl Backend + 'static) -> Result<()> {
29 self.with_mut(|backends| {
30 let name = backend.name();
31 if backends.iter().any(|backend| backend.name() == name) {
32 error!("Attempt to register backend \"{}\" twice", name);
33 return Err(Error::AlreadyRegistered(name.into()));
34 }
35 info!("Registering backend \"{}\"", name);
36 backends.push(Box::new(backend));
37 Ok(())
38 })
39 }
40
41 pub fn create(&self, url: impl ToUrl) -> Result<BoxedConnector> {
43 let url = url.to_url()?;
44 self.with(|backends| {
45 backends
46 .iter()
47 .filter_map(|backend| backend.connector(&url))
48 .next()
49 .ok_or_else(|| {
50 error!("No backends which can handle URL {}", url);
51 url.into()
52 })
53 })
54 }
55
56 fn with_raw<R>(&self, func: impl FnOnce(Backends) -> R) -> R {
57 func(self.backends.clone())
58 }
59
60 fn with<R>(&self, func: impl FnOnce(&[BoxedBackend]) -> R) -> R {
61 self.with_raw(|backends: Backends| {
62 let backends = backends.read().unwrap();
63 func(&backends)
64 })
65 }
66
67 fn with_mut<R>(&self, func: impl FnOnce(&mut Vec<BoxedBackend>) -> R) -> R {
68 self.with_raw(|backends: Backends| {
69 let mut backends = backends.write().unwrap();
70 func(&mut backends)
71 })
72 }
73}