diff --git a/Cargo.lock b/Cargo.lock index a1940446..e6204ccf 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -178,7 +178,6 @@ dependencies = [ "glob", "indexmap 2.2.2", "json5", - "lazy_static", "log", "nom", "notify", diff --git a/Cargo.toml b/Cargo.toml index 93f39c7c..bdbfbbd0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -121,7 +121,6 @@ preserve_order = ["indexmap", "toml?/preserve_order", "serde_json?/preserve_orde async = ["async-trait"] [dependencies] -lazy_static = "1.4" serde = "1.0" nom = "7" diff --git a/examples/global/main.rs b/examples/global/main.rs index 160d8817..0184be45 100644 --- a/examples/global/main.rs +++ b/examples/global/main.rs @@ -1,19 +1,20 @@ #![allow(deprecated)] use config::Config; -use lazy_static::lazy_static; use std::error::Error; +use std::sync::OnceLock; use std::sync::RwLock; -lazy_static! { - static ref SETTINGS: RwLock = RwLock::new(Config::default()); +fn settings() -> &'static RwLock { + static CONFIG: OnceLock> = OnceLock::new(); + CONFIG.get_or_init(|| RwLock::new(Config::default())) } fn try_main() -> Result<(), Box> { // Set property - SETTINGS.write()?.set("property", 42)?; + settings().write()?.set("property", 42)?; // Get property - println!("property: {}", SETTINGS.read()?.get::("property")?); + println!("property: {}", settings().read()?.get::("property")?); Ok(()) } diff --git a/examples/static_env.rs b/examples/static_env.rs index ba3222fc..e95cd532 100644 --- a/examples/static_env.rs +++ b/examples/static_env.rs @@ -1,18 +1,22 @@ +use std::sync::OnceLock; + use config::Config; -lazy_static::lazy_static! { - #[derive(Debug)] - pub static ref CONFIG: Config = Config::builder() - .add_source(config::Environment::with_prefix("APP_NAME").separator("_")) - .build() - .unwrap(); +fn config() -> &'static Config { + static CONFIG: OnceLock = OnceLock::new(); + CONFIG.get_or_init(|| { + Config::builder() + .add_source(config::Environment::with_prefix("APP_NAME").separator("_")) + .build() + .unwrap() + }) } /// Get a configuration value from the static configuration object pub fn get<'a, T: serde::Deserialize<'a>>(key: &str) -> T { // You shouldn't probably do it like that and actually handle that error that might happen // here, but for the sake of simplicity, we do it like this here - CONFIG.get::(key).unwrap() + config().get::(key).unwrap() } fn main() { diff --git a/examples/watch/main.rs b/examples/watch/main.rs index 7f35e869..25df2e43 100644 --- a/examples/watch/main.rs +++ b/examples/watch/main.rs @@ -4,22 +4,26 @@ use notify::{Event, RecommendedWatcher, RecursiveMode, Watcher}; use std::collections::HashMap; use std::path::Path; use std::sync::mpsc::channel; +use std::sync::OnceLock; use std::sync::RwLock; use std::time::Duration; -lazy_static::lazy_static! { - static ref SETTINGS: RwLock = RwLock::new({ +fn settings() -> &'static RwLock { + static CONFIG: OnceLock> = OnceLock::new(); + CONFIG.get_or_init(|| { let mut settings = Config::default(); - settings.merge(File::with_name("examples/watch/Settings.toml")).unwrap(); - settings - }); + .merge(File::with_name("examples/watch/Settings.toml")) + .unwrap(); + + RwLock::new(settings) + }) } fn show() { println!( " * Settings :: \n\x1b[31m{:?}\x1b[0m", - SETTINGS + settings() .read() .unwrap() .clone() @@ -58,7 +62,7 @@ fn watch() -> ! { .. })) => { println!(" * Settings.toml written; refreshing configuration ..."); - SETTINGS.write().unwrap().refresh().unwrap(); + settings().write().unwrap().refresh().unwrap(); show(); } diff --git a/src/file/format/mod.rs b/src/file/format/mod.rs index 1242d153..055a4ce5 100644 --- a/src/file/format/mod.rs +++ b/src/file/format/mod.rs @@ -1,10 +1,6 @@ -// If no features are used, there is an "unused mut" warning in `ALL_EXTENSIONS` -// BUG: ? For some reason this doesn't do anything if I try and function scope this -#![allow(unused_mut)] - -use lazy_static::lazy_static; use std::collections::HashMap; use std::error::Error; +use std::sync::OnceLock; use crate::map::Map; use crate::{file::FileStoredFormat, value::Value, Format}; @@ -57,10 +53,11 @@ pub enum FileFormat { Json5, } -lazy_static! { - #[doc(hidden)] - // #[allow(unused_mut)] ? - pub static ref ALL_EXTENSIONS: HashMap> = { +pub(crate) fn all_extensions() -> &'static HashMap> { + #![allow(unused_mut)] // If no features are used, there is an "unused mut" warning in `all_extensions` + + static ALL_EXTENSIONS: OnceLock>> = OnceLock::new(); + ALL_EXTENSIONS.get_or_init(|| { let mut formats: HashMap> = HashMap::new(); #[cfg(feature = "toml")] @@ -82,15 +79,15 @@ lazy_static! { formats.insert(FileFormat::Json5, vec!["json5"]); formats - }; + }) } impl FileFormat { pub(crate) fn extensions(&self) -> &'static [&'static str] { // It should not be possible for this to fail // A FileFormat would need to be declared without being added to the - // ALL_EXTENSIONS map. - ALL_EXTENSIONS.get(self).unwrap() + // all_extensions map. + all_extensions().get(self).unwrap() } pub(crate) fn parse( diff --git a/src/file/source/file.rs b/src/file/source/file.rs index 8ee5d315..0e0687c2 100644 --- a/src/file/source/file.rs +++ b/src/file/source/file.rs @@ -5,7 +5,7 @@ use std::io; use std::path::PathBuf; use crate::file::{ - format::ALL_EXTENSIONS, source::FileSourceResult, FileSource, FileStoredFormat, Format, + format::all_extensions, source::FileSourceResult, FileSource, FileStoredFormat, Format, }; /// Describes a file sourced from a file @@ -38,7 +38,7 @@ impl FileSourceFile { return if let Some(format) = format_hint { Ok((filename, Box::new(format))) } else { - for (format, extensions) in ALL_EXTENSIONS.iter() { + for (format, extensions) in all_extensions().iter() { if extensions.contains( &filename .extension() @@ -75,7 +75,7 @@ impl FileSourceFile { } None => { - for format in ALL_EXTENSIONS.keys() { + for format in all_extensions().keys() { for ext in format.extensions() { filename.set_extension(ext);