tower_web/config/
mod.rs

1//! Application level configuration.
2//!
3//! Provides infrastructure for application level configuration. Configuration
4//! values may be set and retrieved by type.
5
6use std::any::{Any, TypeId};
7use std::sync::Arc;
8use std::collections::HashMap;
9use std::hash::{BuildHasherDefault, Hasher};
10use std::fmt;
11
12type AnyMap = HashMap<TypeId, Box<Any + Send + Sync>, BuildHasherDefault<IdHasher>>;
13
14#[derive(Debug, Default)]
15struct IdHasher(u64);
16
17impl Hasher for IdHasher {
18    fn write(&mut self, _: &[u8]) {
19        unreachable!("TypeId calls write_u64");
20    }
21
22    #[inline]
23    fn write_u64(&mut self, id: u64) {
24        self.0 = id;
25    }
26
27    #[inline]
28    fn finish(&self) -> u64 {
29        self.0
30    }
31}
32
33pub(crate) struct ConfigBuilder {
34    inner: AnyMap,
35}
36
37impl ConfigBuilder {
38    pub(crate) fn new() -> Self {
39        Self { inner: AnyMap::default() }
40    }
41
42    pub(crate) fn insert<T: Send + Sync + 'static>(mut self, val: T) -> Self {
43        self.inner.insert(TypeId::of::<T>(), Box::new(val));
44        self
45    }
46
47    pub(crate) fn into_config(self) -> Config {
48        Config { inner: Arc::new(self.inner) }
49    }
50}
51
52impl fmt::Debug for ConfigBuilder {
53    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
54        f.debug_struct("ConfigBuilder")
55            .finish()
56    }
57}
58
59/// A type of application level configuration.
60#[derive(Clone)]
61pub struct Config {
62    inner: Arc<AnyMap>,
63}
64
65impl Config {
66    /// Get the configuration value of the specified type.
67    ///
68    /// If a configuration value of type `T` is stored in `Config`, it is
69    /// returned. Otherwise, `None` is returned.
70    pub fn get<T: 'static>(&self) -> Option<&T> {
71        self.inner
72            .get(&TypeId::of::<T>())
73            .and_then(|boxed| {
74                (&**boxed as &Any).downcast_ref()
75            })
76    }
77}
78
79impl fmt::Debug for Config {
80    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
81        f.debug_struct("Config")
82            .finish()
83    }
84}