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 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147
#![warn(missing_docs)]
/*
* SPDX-FileCopyrightText: Peter Pentchev <roam@ringlet.net>
* SPDX-License-Identifier: BSD-2-Clause
*/
//! Parse configuration files.
//!
//! The `confget` library parses configuration files (currently INI-style
//! files only) and allows a program to use the values defined in them.
//! It provides various options for selecting the variable names and
//! values to return and the configuration file sections to fetch them from.
//!
//! The `confget` library may also be used as a command-line tool with
//! the same interface as the C implementation.
//!
//! # Quick-and-easy parsing of INI-style files
//!
//! The [`read_ini_file`] function will parse
//! an INI-style file and return a hashmap of the values found in its
//! various sections, as well as the name of the first section found in
//! the file (or the one specified in the configuration if
//! the [`Config::section_override`] option is enabled).
//!
//! ```
//! # use std::error::Error;
//! # use std::fs;
//! # use std::path::Path;
//!
//! # use confget::Config;
//!
//! # fn main() -> Result<(), Box<dyn Error>> {
//! # let tempd_obj = tempfile::tempdir()?;
//! # let confdir: &Path = tempd_obj.as_ref();
//! # fs::write(&confdir.join("config.ini"), "var = value\n");
//! // Default configuration except for the filename.
//! let config = Config {
//! filename: Some(confdir.join("config.ini").to_str().unwrap().to_string()),
//! ..Config::default()
//! };
//! let (data, first_section) = confget::read_ini_file(&config)?;
//! # Ok(())
//! # }
//! ```
//!
//! For the crate's change history, see
//! the [CHANGES](https://gitlab.com/confget/confget/-/blob/master/CHANGES)
//! file in the source distribution.
#![doc(html_root_url = "https://docs.rs/confget/5.1.2")]
// We want to re-export some defs::* types to make it easier on the consumers.
#![allow(clippy::pub_use)]
#[cfg(feature = "ini-regex")]
use crate::backend::ini_re::IniREBackend;
#[cfg(feature = "ini-nom")]
use crate::backend::ini_nom::IniNomBackend;
use crate::backend::{Backend, DataRead};
pub mod backend;
pub mod defs;
pub mod format;
#[cfg(test)]
pub mod tests;
pub use defs::{BackendKind, ConfgetError, Config, FileData, SectionData};
/// Construct an object of the specified backend type.
///
/// The `backend` member of the [`Config`] object
/// specifies the type of the backend to construct.
///
/// Some backends may perform validation at object creation time;
/// the "ini" one currently does not, so this method will always succeed.
///
/// # Errors
///
/// None for the present, but future backends may check for configuration
/// inconsistencies.
#[inline]
pub fn get_backend<'cfg>(
config: &'cfg Config,
) -> Result<Box<dyn Backend<'cfg> + 'cfg>, ConfgetError> {
match config.backend {
#[cfg(feature = "ini-regex")]
BackendKind::IniRE => Ok(Box::new(IniREBackend::from_config(config)?)),
#[cfg(feature = "ini-nom")]
BackendKind::IniNom => Ok(Box::new(IniNomBackend::from_config(config)?)),
}
}
/// Read an INI-style file with the specified configuration.
///
/// Internally constructs an "ini" backend and invokes its
/// [`Backend::read_file`] method.
/// The [`Config`] object's `filename` member must contain a value.
///
/// # Errors
///
/// The same as from [`IniREBackend::read_file`].
#[inline]
pub fn read_ini_file(config: &Config) -> Result<DataRead, ConfgetError> {
#[cfg(feature = "ini-nom")]
if config.backend == BackendKind::IniNom {
let ini = IniNomBackend::from_config(config)?;
return ini.read_file();
}
#[cfg(feature = "ini-regex")]
if config.backend == BackendKind::IniRE {
let ini = IniREBackend::from_config(config)?;
return ini.read_file();
}
Err(ConfgetError::Config(format!(
"confget::read_ini_file() invoked for a non-INI-style backend {backend}",
backend = config.backend.as_ref()
)))
}
/// Build an array of features supported by the confget library based on
/// the enabled crate features.
#[inline]
#[allow(clippy::must_use_candidate)]
pub fn features() -> Vec<(&'static str, &'static str)> {
let mut res = vec![
("BASE", env!("CARGO_PKG_VERSION")),
("REGEX", "1.0"),
("REGEX_IMPL_RUST_CRATE_REGEX", "1"),
("INI_BACKEND", BackendKind::get_preferred_ini_backend_name()),
];
#[cfg(feature = "ini-nom")]
{
res.push(("INI_NOM", "1.0"));
}
#[cfg(feature = "ini-regex")]
{
res.push(("INI_REGEX", "1.0"));
}
res
}