mirror of
https://github.com/OMGeeky/confique.git
synced 2025-12-27 06:29:27 +01:00
Disable some code (and fix others) when no features are enabled
This commit is contained in:
@@ -15,6 +15,11 @@ categories = ["config"]
|
||||
exclude = [".github"]
|
||||
|
||||
|
||||
[[example]]
|
||||
name = "simple"
|
||||
required-features = ["toml"]
|
||||
|
||||
|
||||
[features]
|
||||
default = ["toml", "yaml"]
|
||||
yaml = ["serde_yaml"]
|
||||
|
||||
@@ -1,6 +1,11 @@
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
use std::path::PathBuf;
|
||||
|
||||
use crate::{Config, Error, File, Partial};
|
||||
use crate::{Config, Error, Partial};
|
||||
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
use crate::File;
|
||||
|
||||
|
||||
|
||||
/// Convenience builder to configure, load and merge multiple configuration
|
||||
@@ -25,6 +30,7 @@ impl<C: Config> Builder<C> {
|
||||
///
|
||||
/// The file is not considered required: if the file does not exist, an
|
||||
/// empty configuration (`C::Partial::empty()`) is used for this layer.
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
pub fn file(mut self, path: impl Into<PathBuf>) -> Self {
|
||||
self.sources.push(Source::File(path.into()));
|
||||
self
|
||||
@@ -51,6 +57,7 @@ impl<C: Config> Builder<C> {
|
||||
let mut partial = C::Partial::empty();
|
||||
for source in self.sources {
|
||||
let layer = match source {
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
Source::File(path) => File::new(path)?.load()?,
|
||||
Source::Env => C::Partial::from_env()?,
|
||||
Source::Preloaded(p) => p,
|
||||
@@ -64,6 +71,7 @@ impl<C: Config> Builder<C> {
|
||||
}
|
||||
|
||||
enum Source<C: Config> {
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
File(PathBuf),
|
||||
Env,
|
||||
Preloaded(C::Partial),
|
||||
|
||||
33
src/error.rs
33
src/error.rs
@@ -1,4 +1,8 @@
|
||||
use std::{fmt, path::PathBuf};
|
||||
use std::fmt;
|
||||
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
use std::path::PathBuf;
|
||||
|
||||
|
||||
|
||||
/// Type describing all errors that can occur in this library.
|
||||
@@ -13,12 +17,14 @@ pub(crate) enum ErrorInner {
|
||||
MissingValue(String),
|
||||
|
||||
/// An IO error occured, e.g. when reading a file.
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
Io {
|
||||
path: Option<PathBuf>,
|
||||
err: std::io::Error,
|
||||
},
|
||||
|
||||
/// Returned by `Source::load` implementations when deserialization fails.
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
Deserialization {
|
||||
/// A human readable description for the error message, describing from
|
||||
/// what source it was attempted to deserialize. Completes the sentence
|
||||
@@ -39,17 +45,20 @@ pub(crate) enum ErrorInner {
|
||||
/// Returned by the [`Source`] impls for `Path` and `PathBuf` if the file
|
||||
/// extension is not supported by confique or if the corresponding Cargo
|
||||
/// feature of confique was not enabled.
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
UnsupportedFileFormat {
|
||||
path: PathBuf,
|
||||
},
|
||||
|
||||
/// Returned by the [`Source`] impls for `Path` and `PathBuf` if the path
|
||||
/// does not contain a file extension.
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
MissingFileExtension {
|
||||
path: PathBuf,
|
||||
},
|
||||
|
||||
/// A file source was marked as required but the file does not exist.
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
MissingRequiredFile {
|
||||
path: PathBuf,
|
||||
}
|
||||
@@ -58,13 +67,18 @@ pub(crate) enum ErrorInner {
|
||||
impl std::error::Error for Error {
|
||||
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
||||
match &*self.inner {
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
ErrorInner::Io { err, .. } => Some(err),
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
ErrorInner::Deserialization { err, .. } => Some(&**err),
|
||||
ErrorInner::MissingValue(_)
|
||||
| ErrorInner::EnvDeserialization { .. }
|
||||
| ErrorInner::UnsupportedFileFormat { .. }
|
||||
| ErrorInner::MissingFileExtension { .. }
|
||||
| ErrorInner::MissingRequiredFile { .. } => None,
|
||||
ErrorInner::MissingValue(_) => None,
|
||||
ErrorInner::EnvDeserialization { .. } => None,
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
ErrorInner::UnsupportedFileFormat { .. } => None,
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
ErrorInner::MissingFileExtension { .. } => None,
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
ErrorInner::MissingRequiredFile { .. } => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -75,18 +89,22 @@ impl fmt::Display for Error {
|
||||
ErrorInner::MissingValue(path) => {
|
||||
std::write!(f, "required configuration value is missing: '{}'", path)
|
||||
}
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
ErrorInner::Io { path: Some(path), .. } => {
|
||||
std::write!(f,
|
||||
"IO error occured while reading configuration file '{}'",
|
||||
path.display(),
|
||||
)
|
||||
}
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
ErrorInner::Io { path: None, .. } => {
|
||||
std::write!(f, "IO error occured while loading configuration")
|
||||
}
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
ErrorInner::Deserialization { source: Some(source), .. } => {
|
||||
std::write!(f, "failed to deserialize configuration from {}", source)
|
||||
}
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
ErrorInner::Deserialization { source: None, .. } => {
|
||||
std::write!(f, "failed to deserialize configuration")
|
||||
}
|
||||
@@ -98,18 +116,21 @@ impl fmt::Display for Error {
|
||||
msg,
|
||||
)
|
||||
}
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
ErrorInner::UnsupportedFileFormat { path } => {
|
||||
std::write!(f,
|
||||
"unknown configuration file format/extension: '{}'",
|
||||
path.display(),
|
||||
)
|
||||
}
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
ErrorInner::MissingFileExtension { path } => {
|
||||
std::write!(f,
|
||||
"cannot guess configuration file format due to missing file extension in '{}'",
|
||||
path.display(),
|
||||
)
|
||||
}
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
ErrorInner::MissingRequiredFile { path } => {
|
||||
std::write!(f,
|
||||
"required configuration file does not exist: '{}'",
|
||||
|
||||
19
src/lib.rs
19
src/lib.rs
@@ -88,9 +88,11 @@
|
||||
//! # #[derive(Config)]
|
||||
//! # struct Conf {}
|
||||
//! // Load from a single file only.
|
||||
//! # #[cfg(feature = "toml")]
|
||||
//! let config = Conf::from_file("config.toml")?;
|
||||
//!
|
||||
//! // Or load from multiple sources (higher priority sources are listed first).
|
||||
//! # #[cfg(feature = "toml")]
|
||||
//! let config = Conf::builder()
|
||||
//! .env()
|
||||
//! .file("config.toml")
|
||||
@@ -113,7 +115,10 @@
|
||||
//! [`Partial::default_values`] as the last layer.
|
||||
//!
|
||||
//! ```rust,no_run
|
||||
//! # #[cfg(feature = "toml")]
|
||||
//! use confique::{Config, File, FileFormat, Partial};
|
||||
//! # #[cfg(not(feature = "toml"))]
|
||||
//! # use confique::{Config, Partial};
|
||||
//!
|
||||
//! #[derive(Config)]
|
||||
//! struct Conf {
|
||||
@@ -121,9 +126,12 @@
|
||||
//! }
|
||||
//!
|
||||
//! type PartialConf = <Conf as Config>::Partial;
|
||||
//! # #[cfg(feature = "toml")]
|
||||
//! let from_file: PartialConf = File::with_format("/etc/foo/config", FileFormat::Toml)
|
||||
//! .required()
|
||||
//! .load()?;
|
||||
//! # #[cfg(not(feature = "toml"))]
|
||||
//! let from_file: PartialConf = todo!();
|
||||
//! let manual = PartialConf {
|
||||
//! // Remember: all fields in the partial types are `Option`s!
|
||||
//! foo: Some(3.14),
|
||||
@@ -149,6 +157,7 @@
|
||||
//! - `toml`: enables TOML support and adds the `toml` dependency.
|
||||
//! - `yaml`: enables YAML support and adds the `serde_yaml` dependency.
|
||||
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
use std::path::PathBuf;
|
||||
|
||||
use serde::Deserialize;
|
||||
@@ -159,12 +168,14 @@ pub mod internal;
|
||||
mod builder;
|
||||
mod env;
|
||||
mod error;
|
||||
mod file;
|
||||
pub mod meta;
|
||||
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
mod format;
|
||||
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
mod file;
|
||||
|
||||
#[cfg(feature = "toml")]
|
||||
pub mod toml;
|
||||
|
||||
@@ -176,9 +187,11 @@ pub use serde;
|
||||
pub use self::{
|
||||
builder::Builder,
|
||||
error::Error,
|
||||
file::{File, FileFormat},
|
||||
};
|
||||
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
pub use crate::file::{File, FileFormat};
|
||||
|
||||
|
||||
/// Derives (automatically implements) [`Config`] for a struct.
|
||||
///
|
||||
@@ -367,6 +380,7 @@ pub trait Config: Sized {
|
||||
/// port: u16,
|
||||
/// }
|
||||
///
|
||||
/// #[cfg(feature = "toml")]
|
||||
/// let conf = Conf::builder()
|
||||
/// .env()
|
||||
/// .file("app.toml")
|
||||
@@ -400,6 +414,7 @@ pub trait Config: Sized {
|
||||
///
|
||||
/// let conf = Conf::from_file("config.toml");
|
||||
/// ```
|
||||
#[cfg(any(feature = "toml", feature = "yaml"))]
|
||||
fn from_file(path: impl Into<PathBuf>) -> Result<Self, Error> {
|
||||
let default_values = Self::Partial::default_values();
|
||||
let mut file = File::new(path)?;
|
||||
|
||||
Reference in New Issue
Block a user