1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
#![feature(drop_types_in_const)]

#![allow(unknown_lints)]

#[cfg(feature = "toml")]
extern crate toml;

#[cfg(feature = "json")]
extern crate serde_json;

mod value;
mod source;
mod file;
mod env;
mod config;

use std::error::Error;
use std::sync::{Once, ONCE_INIT, RwLock};
use std::borrow::Cow;

pub use source::{Source, SourceBuilder};
pub use file::{File, FileFormat};
pub use env::Environment;

pub use value::Value;

pub use config::Config;

// Global configuration
static mut CONFIG: Option<RwLock<Config<'static>>> = None;
static CONFIG_INIT: Once = ONCE_INIT;

// Get the global configuration instance
pub fn global() -> &'static mut RwLock<Config<'static>> {
    unsafe {
        CONFIG_INIT.call_once(|| {
            CONFIG = Some(Default::default());
        });

        CONFIG.as_mut().unwrap()
    }
}

pub fn merge<T>(source: T) -> Result<(), Box<Error>>
    where T: SourceBuilder
{
    global().write().unwrap().merge(source)
}

pub fn set_default<T>(key: &str, value: T) -> Result<(), Box<Error>>
    where T: Into<Value<'static>>
{
    global().write().unwrap().set_default(key, value)
}

pub fn set<T>(key: &str, value: T) -> Result<(), Box<Error>>
    where T: Into<Value<'static>>
{
    global().write().unwrap().set(key, value)
}

pub fn get<'a>(key: &str) -> Option<Cow<'a, Value>> {
    // TODO(~): Should this panic! or return None with an error message?
    //          Make an issue if you think it should be an error message.
    let r = global().read().unwrap();

    let c = &*r;

    // TODO(@rust): Figure out how to not to use unsafe here
    unsafe {
        let c: &'static Config = std::mem::transmute(c);
        c.get(key)
    }
}

pub fn get_str<'a>(key: &str) -> Option<Cow<'a, str>> {
    let r = global().read().unwrap();

    unsafe {
        let c: &'static Config = std::mem::transmute(&*r);
        c.get_str(key)
    }
}

pub fn get_int(key: &str) -> Option<i64> {
    let r = global().read().unwrap();

    unsafe {
        let c: &'static Config = std::mem::transmute(&*r);
        c.get_int(key)
    }
}

pub fn get_float(key: &str) -> Option<f64> {
    let r = global().read().unwrap();

    unsafe {
        let c: &'static Config = std::mem::transmute(&*r);
        c.get_float(key)
    }
}

pub fn get_bool(key: &str) -> Option<bool> {
    let r = global().read().unwrap();

    unsafe {
        let c: &'static Config = std::mem::transmute(&*r);
        c.get_bool(key)
    }
}