use crate::{ext::*, *}; use serde::de::DeserializeOwned; use std::{str::FromStr, ops::Deref}; /// Provides binder extension methods for a [`Configuration`](crate::Configuration). pub trait ConfigurationBinder { /// Creates and returns a structure bound to the configuration. fn reify(&self) -> T; /// Binds the configuration to the specified instance. /// /// # Arguments /// /// * `instance` - The instance to bind the configuration to fn bind(&self, instance: &mut T); /// Binds the specified configuration section to the provided instance. /// /// # Arguments /// /// * `key` - The key of the configuration section to bind /// * `instance` - The instance to bind the configuration to fn bind_at(&self, key: impl AsRef, instance: &mut T); /// Gets a typed value from the configuration. /// /// # Arguments /// /// * `key` - The key of the value to retrieve fn get_value(&self, key: impl AsRef) -> Result, T::Err>; /// Gets an optional, typed value from the configuration. /// /// # Arguments /// /// * `key` - The key of the value to retrieve fn get_value_or_default(&self, key: impl AsRef) -> Result; } impl ConfigurationBinder for dyn Configuration + '_ { fn reify(&self) -> T { from_config::(self).unwrap() } fn bind(&self, instance: &mut T) { bind_config(self, instance).unwrap() } fn bind_at(&self, key: impl AsRef, instance: &mut T) { let section = self.section(key.as_ref()); if section.exists() { bind_config(section.deref().as_ref(), instance).unwrap() } } fn get_value(&self, key: impl AsRef) -> Result, T::Err> { let section = self.section(key.as_ref()); let value = if section.exists() { Some(T::from_str(section.value().as_str())?) } else { None }; Ok(value) } fn get_value_or_default(&self, key: impl AsRef) -> Result { let section = self.section(key.as_ref()); let value = if section.exists() { T::from_str(section.value().as_str())? } else { T::default() }; Ok(value) } } impl> ConfigurationBinder for C { fn reify(&self) -> T { from_config::(self.as_ref()).unwrap() } fn bind(&self, instance: &mut T) { bind_config(self.as_ref(), instance).unwrap() } fn bind_at(&self, key: impl AsRef, instance: &mut T) { let section = self.as_ref().section(key.as_ref()); if section.exists() { bind_config(section.deref().as_ref(), instance).unwrap() } } fn get_value(&self, key: impl AsRef) -> Result, T::Err> { let section = self.as_ref().section(key.as_ref()); let value = if section.exists() { Some(T::from_str(section.value().as_str())?) } else { None }; Ok(value) } fn get_value_or_default(&self, key: impl AsRef) -> Result { let section = self.as_ref().section(key.as_ref()); let value = if section.exists() { T::from_str(section.value().as_str())? } else { T::default() }; Ok(value) } }