#env-var #config-parser #config-format #json-configuration #source #environment #yaml

rstdev-config

一个用于管理来自多个源和格式的配置的库

4 个版本

0.1.3 2024 年 3 月 9 日
0.1.2 2024 年 3 月 9 日
0.1.1 2024 年 3 月 9 日
0.1.0 2024 年 3 月 9 日

#3#config-format

Apache-2.0 协议

22KB
411

rstdev-config

rstdev_config 是一个库,用于从多个源和多种格式类型获取配置数据

此库的主要目的是帮助工程师维护他们的配置数据。为了给工程师提供灵活性,它将提供一个基础抽象,使他们能够根据自己的需求创建自己的源适配器和解析器

此库还提供了一个 Source 的实现,该实现能够解析给定的配置。当前支持的格式类型

  • YAML
  • TOML
  • JSON
  • 环境变量数据类型

安装

[dependencies]
rstdev-config = {version = "0.1.3"}

用法

use serde::Deserialize;

use rstdev_config::format::{use_toml, use_env};
use rstdev_config::{Builder, ConfigError};
use rstdev_config::parser::{from_file, from_env};

#[derive(Deserialize)]
struct Config {

}

fn main() -> Result<(), ConfigError> {
    let cfg_file_path = "./test.toml";
    let cfg_file: Config = Builder::new(from_file(cfg_file_path)).fetch()?.parse(use_toml)?;
    let cfg_env: Config = Builder::new(from_env("PREFIX_")).fetch()?.parse(use_env)?;
}

基础抽象

pub trait SourceFormatter<'a, TValue>: Clone {
    fn get_source_value(&'a self) -> TValue;
}

pub trait SourceParser<TFormatter, TValue>
where
    TValue: Clone,
    TFormatter: for<'a> SourceFormatter<'a, TValue>,
{
    fn fetch(&self) -> Result<Source<TFormatter, TValue>, ConfigError>;
}

types::SourceFormatter》的示例实现

#[derive(Clone)]
pub struct Value {
    input: String,
}

impl Value {
    pub fn new(input: String) -> Self {
        Self { input }
    }
}

impl<'a> SourceFormatter<'a, String> for Value {
    fn get_source_value(&'a self) -> String {
        self.input.clone()
    }
}

types::SourceParser》的示例实现

pub struct File {
    filepath: String,
}

impl File {
    pub fn new(filepath: String) -> Self {
        Self { filepath }
    }
}

impl SourceParser<StringValue, String> for File {
    fn fetch(&self) -> Result<Source<StringValue, String>, ConfigError> {
        let content = fs::read_to_string(self.filepath.clone())
            .map_err(|err| ConfigError::ParseError(err.to_string()))?;

        Ok(Source::new(StringValue::new(content)))
    }
}

使用 parser::from_fileBuilder 示例

let cfg: MessageGroup = Builder::new(from_file(toml_file))
    .fetch()?
    .parse(from_toml)?;

parse 方法是 Source 公共方法的一部分

pub fn parse<F, Out>(&self, cb: F) -> Result<Out, ConfigError>
where
    F: FnOnce(St) -> Result<Out, ConfigError>,
    Out: DeserializeOwned,
{
    cb(self.input.get_source_value())
}

use_toml 实际上是一个回调函数,它实现了 FnOnce(St) -> Result<Out, ConfigError>

pub fn use_toml<In, Out>(input: In) -> Result<Out, ConfigError>
where
    In: ToString,
    Out: DeserializeOwned,
{
    let from_toml = toml::from_str(&input.to_string())
        .map_err(|err| ConfigError::FormatError(err.to_string()))?;

    Ok(from_toml)
}

依赖项

~6MB
~118K SLoC