rdbc_rs/future/
datasource.rs1use std::{
6 collections::HashMap,
7 sync::{Arc, Mutex},
8};
9
10use crate::{driver, Database};
11
12use anyhow::*;
13
14use super::ConnectionPool;
15
16pub type BoxedDriver = Box<dyn driver::Driver + 'static>;
17
18#[derive(Clone, Default)]
22#[allow(dead_code)]
23pub struct DataSource {
24 drivers: Arc<Mutex<HashMap<String, Arc<Mutex<BoxedDriver>>>>>,
25}
26
27impl DataSource {
28 pub fn register<S>(&self, name: S, driver: impl driver::Driver + 'static) -> Result<()>
34 where
35 S: Into<String> + AsRef<str>,
36 {
37 let mut drivers = self.drivers.lock().unwrap();
38
39 if drivers.contains_key(name.as_ref()) {
40 return Err(anyhow!("register driver {} twice", name.as_ref()));
41 }
42
43 drivers.insert(name.into(), Arc::new(Mutex::new(Box::new(driver))));
44
45 Ok(())
46 }
47
48 pub fn open_with<S, DB>(&self, name: S, url: S) -> Result<DB>
57 where
58 S: Into<String> + AsRef<str>,
59 DB: ConnectionPool + Sync + Send,
60 {
61 let drivers = self.drivers.lock().unwrap();
62 let driver = drivers.get(name.as_ref());
63
64 if let Some(driver) = driver {
65 DB::new(name, driver.clone(), url)
66 } else {
67 return Err(anyhow!("driver {} not found", name.as_ref()));
68 }
69 }
70
71 pub fn open<S>(&self, name: S, url: S) -> Result<Database>
74 where
75 S: Into<String> + AsRef<str>,
76 {
77 self.open_with(name, url)
78 }
79}
80
81mod global {
82
83 use super::*;
84
85 fn global_datasource() -> &'static mut DataSource {
86 static mut CONF: std::mem::MaybeUninit<DataSource> = std::mem::MaybeUninit::uninit();
87 static ONCE: std::sync::Once = std::sync::Once::new();
88 ONCE.call_once(|| unsafe {
89 CONF.as_mut_ptr().write(DataSource::default());
90 });
91 unsafe { &mut *CONF.as_mut_ptr() }
92 }
93
94 pub fn register<S>(name: S, driver: impl driver::Driver + 'static) -> Result<()>
95 where
96 S: Into<String> + AsRef<str>,
97 {
98 global_datasource().register(name, driver)
99 }
100
101 pub fn open_with<S, DB>(name: S, url: S) -> Result<DB>
102 where
103 S: Into<String> + AsRef<str>,
104 DB: ConnectionPool + Sync + Send,
105 {
106 global_datasource().open_with(name, url)
107 }
108
109 pub fn open<S>(name: S, url: S) -> Result<Database>
110 where
111 S: Into<String> + AsRef<str>,
112 {
113 global_datasource().open_with(name, url)
114 }
115}
116
117pub use global::*;
118
119#[cfg(test)]
120mod tests {
121
122 use crate::driver::Driver;
123
124 use super::DataSource;
125
126 struct NullDriver {}
127
128 impl Driver for NullDriver {
129 fn open(&mut self, _url: &str) -> anyhow::Result<Box<dyn crate::driver::Connection>> {
130 unimplemented!()
131 }
132 }
133
134 #[test]
135 fn test_register() {
136 let ds = DataSource::default();
137
138 _ = ds.register("".to_owned(), NullDriver {});
139 }
140}