use crate::types::{EnvError, EnvType};
use std::collections::HashMap;
use std::marker::PhantomData;
pub trait ContextMarker: Send + Sync + 'static {
type Value: Clone + Send + Sync + 'static;
}
#[derive(Clone)]
pub struct Context<M: ContextMarker> {
env_values: HashMap<EnvType, M::Value>,
default: Option<M::Value>,
_marker: PhantomData<M>,
}
impl<M: ContextMarker> Default for Context<M> {
fn default() -> Self {
Self {
env_values: HashMap::new(),
default: None,
_marker: PhantomData,
}
}
}
impl<M: ContextMarker> Context<M> {
pub fn get_for_env(&self, env: &EnvType) -> Option<M::Value> {
self.env_values
.get(env)
.cloned()
.or_else(|| self.default.clone())
}
pub fn try_get_for_env(&self, env: &EnvType) -> Result<M::Value, EnvError> {
self.get_for_env(env).ok_or(EnvError::ContextValueNotFound)
}
}
pub struct ContextBuilder<M: ContextMarker> {
env_values: HashMap<EnvType, M::Value>,
default: Option<M::Value>,
_marker: PhantomData<M>,
}
impl<M: ContextMarker> Default for ContextBuilder<M> {
fn default() -> Self {
Self {
env_values: HashMap::new(),
default: None,
_marker: PhantomData,
}
}
}
impl<M: ContextMarker> ContextBuilder<M> {
pub fn with_value(mut self, env: EnvType, value: M::Value) -> Self {
self.env_values.insert(env, value);
self
}
pub fn with_values<I>(mut self, envs: I, value: M::Value) -> Self
where
I: IntoIterator<Item = EnvType>,
M::Value: Clone,
{
for env in envs {
self.env_values.insert(env, value.clone());
}
self
}
pub fn with_default(mut self, value: M::Value) -> Self {
self.default = Some(value);
self
}
pub fn build(self) -> Context<M> {
Context {
env_values: self.env_values,
default: self.default,
_marker: PhantomData,
}
}
}