Skip to main content

qubit_config/source/
config_source.rs

1/*******************************************************************************
2 *
3 *    Copyright (c) 2025 - 2026 Haixing Hu.
4 *
5 *    SPDX-License-Identifier: Apache-2.0
6 *
7 *    Licensed under the Apache License, Version 2.0.
8 *
9 ******************************************************************************/
10use crate::{
11    Config,
12    ConfigResult,
13};
14
15/// Trait for configuration sources
16///
17/// Implementors of this trait can load configuration data and populate a
18/// [`Config`] object.
19///
20/// # Examples
21///
22/// ```rust
23/// use qubit_config::{Config, source::ConfigSource};
24///
25/// struct MySource;
26///
27/// impl ConfigSource for MySource {
28///     fn load(&self, config: &mut Config) -> qubit_config::ConfigResult<()> {
29///         config.set("key", "value")?;
30///         Ok(())
31///     }
32/// }
33/// ```
34///
35pub trait ConfigSource {
36    /// Loads configuration data into the provided `Config` object
37    ///
38    /// # Parameters
39    ///
40    /// * `config` - The configuration object to populate
41    ///
42    /// # Returns
43    ///
44    /// Returns `Ok(())` on success, or a `ConfigError` on failure
45    fn load(&self, config: &mut Config) -> ConfigResult<()>;
46
47    /// Loads configuration data into an already-staged `Config` object.
48    ///
49    /// Built-in sources override this method to avoid cloning when the caller
50    /// has already staged a transaction. Custom implementations can rely on
51    /// the default, which delegates to [`Self::load`].
52    ///
53    /// # Parameters
54    ///
55    /// * `config` - The staged configuration object to populate
56    ///
57    /// # Returns
58    ///
59    /// Returns `Ok(())` on success, or a `ConfigError` on failure
60    #[inline]
61    fn load_into(&self, config: &mut Config) -> ConfigResult<()> {
62        self.load(config)
63    }
64}
65
66/// Runs a source load against a cloned config and commits only on success.
67///
68/// # Parameters
69///
70/// * `source` - Source whose non-transactional loader should be staged.
71/// * `config` - Target configuration to update atomically.
72///
73/// # Returns
74///
75/// Returns `Ok(())` after committing the staged config, or propagates the
76/// source error while leaving `config` unchanged.
77pub(crate) fn load_transactionally<S>(source: &S, config: &mut Config) -> ConfigResult<()>
78where
79    S: ConfigSource + ?Sized,
80{
81    let mut staged = config.clone();
82    source.load_into(&mut staged)?;
83    *config = staged;
84    Ok(())
85}