use serde::{Serialize, de::DeserializeOwned};
use super::ConfigResult;
#[async_trait::async_trait]
pub trait ConfigProvider: Send + Sync {
fn name(&self) -> &str;
async fn get_raw(&self, key: &str) -> ConfigResult<Option<String>>;
async fn set_raw(&self, key: &str, value: &str) -> ConfigResult<()>;
async fn delete(&self, key: &str) -> ConfigResult<bool>;
async fn list_keys(&self, prefix: &str) -> ConfigResult<Vec<String>>;
}
pub trait ConfigProviderExt: ConfigProvider {
fn get<T: DeserializeOwned + Send>(
&self,
key: &str,
) -> impl std::future::Future<Output = ConfigResult<Option<T>>> + Send
where
Self: Sync,
{
async move {
match self.get_raw(key).await? {
Some(raw) => {
let value: T = serde_json::from_str(&raw).map_err(|e| {
super::ConfigError::InvalidValue {
key: key.to_string(),
message: e.to_string(),
}
})?;
Ok(Some(value))
}
None => Ok(None),
}
}
}
fn set<T: Serialize + Send + Sync>(
&self,
key: &str,
value: &T,
) -> impl std::future::Future<Output = ConfigResult<()>> + Send
where
Self: Sync,
{
async move {
let raw = serde_json::to_string(value)?;
self.set_raw(key, &raw).await
}
}
}
impl<P: ConfigProvider + ?Sized> ConfigProviderExt for P {}