#![deny(missing_docs)]
mod layers;
use std::path::{Path, PathBuf};
use thiserror::Error as ThisError;
pub use layers::{Builder, Format, Source};
pub use layeredconf_derive::LayeredConf;
pub type Result<T> = std::result::Result<T, Error>;
#[derive(ThisError, Debug)]
pub enum Error {
#[error("Solidify failed, missing fields {missing:?}")]
SolidifyFailedMissing {
missing: Vec<String>,
},
#[error("Solidify failed, no layers")]
SolidifyFailedNoLayers,
#[error("Unknown extension {extension:?}")]
UnknownExtension {
extension: Option<String>,
},
#[error("Auto format detection failed")]
AutoFormatFailed,
#[error("Loop detected loading config files")]
LoopingLoadConfig {
parents: Vec<Source>,
path: PathBuf,
},
#[error("Path canonicalization error {wrapped:?} for {path:?}")]
PathCanonicalization {
wrapped: std::io::Error,
path: PathBuf,
},
#[error("File not found {path:?}")]
FileNotFound {
path: PathBuf,
},
#[error("Error getting current directory {wrapped:?}")]
CurrentDir {
wrapped: std::io::Error,
},
#[error("Error getting parent directory {path:?}")]
ParentDir {
path: PathBuf,
},
#[error("I/O Error {wrapped:?} for {path:?}")]
IoError {
wrapped: std::io::Error,
path: PathBuf,
},
#[error("Json Error {wrapped:?}")]
JsonError {
wrapped: serde_json::Error,
},
#[error("Toml Error {wrapped:?}")]
TomlError {
wrapped: toml::de::Error,
},
#[error("Yaml Error {wrapped:?}")]
YamlError {
wrapped: serde_yaml::Error,
},
}
pub(crate) fn map_io_error(path: &'_ Path) -> impl Fn(std::io::Error) -> Error + '_ {
move |wrapped| {
let path = path.to_path_buf();
match wrapped.kind() {
std::io::ErrorKind::NotFound => Error::FileNotFound { path },
_ => Error::IoError { wrapped, path },
}
}
}
pub(crate) fn map_canonicalization_error(path: &'_ Path) -> impl Fn(std::io::Error) -> Error + '_ {
move |wrapped| {
let path = path.to_path_buf();
match wrapped.kind() {
std::io::ErrorKind::NotFound => Error::FileNotFound { path },
_ => Error::PathCanonicalization { path, wrapped },
}
}
}
impl From<serde_json::Error> for Error {
fn from(wrapped: serde_json::Error) -> Self {
Error::JsonError { wrapped }
}
}
impl From<toml::de::Error> for Error {
fn from(wrapped: toml::de::Error) -> Self {
Error::TomlError { wrapped }
}
}
impl From<serde_yaml::Error> for Error {
fn from(wrapped: serde_yaml::Error) -> Self {
Error::YamlError { wrapped }
}
}
#[doc(hidden)]
pub trait LayeredConfSolid {
type Layer: LayeredConfLayer + Default + serde::de::DeserializeOwned;
}
#[doc(hidden)]
pub trait LayeredConfLayer {
type Config: LayeredConfSolid + serde::de::DeserializeOwned;
fn load_configs(&self) -> Vec<PathBuf>;
fn default_layer() -> Self;
}
#[doc(hidden)]
pub trait LayeredConfMerge<TLayer> {
fn merge_from(&mut self, other: &TLayer);
}
#[doc(hidden)]
pub trait LayeredConfSolidify<TSolid> {
fn solidify(&self) -> Result<TSolid>;
}