-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
11 changed files
with
459 additions
and
40 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,135 @@ | ||
|
||
# High-Performance Rust Configuration System | ||
|
||
Hyperparameter is a high-performance configuration system designed for Rust and Python, supporting the following features: | ||
|
||
1. **High Performance**: Provides fast parameter access, allowing users to freely read and write parameters in the code without worrying about performance issues. | ||
2. **Scope Management**: Manages the definition and use of parameters through scopes, ensuring the isolation and safety of parameter values. | ||
3. **Command Line Integration**: Automatically displays all parameters and their help information in the application's command line. | ||
|
||
## Minimal Example | ||
|
||
Here is a simple example demonstrating how to use Hyperparameter to build a command-line program: | ||
|
||
```rust | ||
use clap::Parser; | ||
use hyperparameter::*; | ||
|
||
#[derive(Parser)] | ||
#[command(after_long_help=generate_params_help())] | ||
struct CommandLineArgs { | ||
/// Specifies parameters in the format `-D key=value` on the command line | ||
#[arg(short = 'D', long)] | ||
define: Vec<String>, | ||
} | ||
|
||
fn main() { | ||
let args = CommandLineArgs::parse(); | ||
with_params! { | ||
params ParamScope::from(&args.define); // Receives all parameters from the command line | ||
|
||
// Retrieves the parameter `example.param1`, using a default value of `1` if not specified. | ||
println!("param1={}", get_param!(example.param1, 1)); | ||
// Retrieves the parameter `example.param2`, displaying help information when `<app> --help` is executed. | ||
println!("param2={}", get_param!(example.param2, false, "help for example.param2")); | ||
} | ||
} | ||
``` | ||
When executing `clap_mini --help`, a section `Hyperparameters` appears at the end of the help information, explaining the names of hyperparameters and their help information: | ||
|
||
``` | ||
Usage: clap_mini [OPTIONS] | ||
Options: | ||
-D, --define <DEFINE> | ||
Specifies hyperparameters in the format `-D key=value` via the command line | ||
-h, --help | ||
Print help (see a summary with '-h') | ||
Hyperparameters: | ||
example.param2 | ||
help for example.param2 | ||
``` | ||
Following the prompt, you can specify the parameter value using `-D example.param2=<value>`: | ||
|
||
```shell | ||
$ clap_mini # Default values | ||
param1=1 | ||
param2=false | ||
|
||
$ clap_mini -D example.param2=true | ||
param1=1 | ||
param2=true | ||
``` | ||
|
||
## Using Configuration Files | ||
|
||
Hyperparameter also supports the use of configuration files. The following example shows how to integrate configuration files, command-line parameters, and user-defined configurations: | ||
|
||
```rust | ||
use std::path::Path; | ||
|
||
use clap::Parser; | ||
use config::{self, File}; | ||
use hyperparameter::*; | ||
|
||
#[derive(Parser)] | ||
#[command(after_long_help=generate_params_help())] | ||
struct CommandLineArgs { | ||
/// Specifies parameters in the format `-D key=value` on the command line | ||
#[arg(short = 'D', long)] | ||
define: Vec<String>, | ||
|
||
/// Specifies the configuration file path in the format `-C <path>` on the command line | ||
#[arg(short = 'C', long, default_value = "examples/rust/cfg.toml")] | ||
config: String, | ||
} | ||
|
||
fn main() { | ||
let args = CommandLineArgs::parse(); | ||
let config_path = Path::new(&args.config); | ||
let config = config::Config::builder() | ||
.add_source(File::from(config_path)) | ||
.build().unwrap(); | ||
|
||
println!("param1={} // No scope", get_param!(example.param1, "default".to_string())); | ||
|
||
with_params! { // Configuration file parameter scope | ||
params config.param_scope(); | ||
|
||
println!("param1={} // cfg file scope", get_param!(example.param1, "default".to_string())); | ||
with_params! { // Command-line arguments scope | ||
params ParamScope::from(&args.define); | ||
|
||
println!("param1={} // cmdline args scope", get_param!(example.param1, "default".to_string(), "Example param1")); | ||
with_params! { // User-defined scope | ||
set example.param1= "scoped".to_string(); | ||
|
||
println!("param1={} // user-defined scope", get_param!(example.param1, "default".to_string())); | ||
} | ||
} | ||
} | ||
} | ||
``` | ||
Directly executing the command `clap_layered` yields the following output: | ||
|
||
``` | ||
param1=default // No scope # Outside any specific scope | ||
param1=from config // cfg file scope # Entered configuration file scope, parameter value affected by the config file | ||
param1=from config // cmdline args scope # Entered command-line scope, command-line overrides config file | ||
param1=scoped // user-defined scope # Entered user-defined scope, custom value overrides command-line | ||
``` | ||
As can be seen: | ||
1. Nested scopes override layer by layer, with parameters in an inner scope overriding those in an outer scope. | ||
2. The command-line scope did not specify the parameter, thus inheriting the value from the outer scope. | ||
|
||
If the command line specifies the value of `example.param1`, the following input is obtained: | ||
|
||
```shell | ||
$ clap_layered -D example.param1="from cmdline" | ||
param1=default // No scope | ||
param1=from config // cfg file scope | ||
param1=from cmdline // cmdline args scope | ||
param1=scoped // user-defined scope | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,131 @@ | ||
# 高性能Rust配置系统 | ||
|
||
Hyperparameter 是一个为 Rust 和 Python 设计的高性能配置系统,它支持以下特性: | ||
|
||
1. 高性能:提供快速的参数访问,允许用户在代码中自由读写参数,无需担心性能问题。 | ||
2. 作用域管理:通过作用域管理参数的定义和使用,确保参数值的隔离和安全。 | ||
3. 命令行集成:支持在应用的命令行中自动展示所有参数及其帮助信息。 | ||
|
||
|
||
## 最小示例 | ||
|
||
以下是一个简单示例,展示如何使用 Hyperparameter 构建一个命令行程序: | ||
```rust | ||
use clap::Parser; | ||
use hyperparameter::*; | ||
|
||
#[derive(Parser)] | ||
#[command(after_long_help=generate_params_help())] | ||
struct CommandLineArgs { | ||
/// 在命令行以`-D key=value`格式指定参数 | ||
#[arg(short = 'D', long)] | ||
define: Vec<String>, | ||
} | ||
|
||
fn main() { | ||
let args = CommandLineArgs::parse(); | ||
with_params! { | ||
params ParamScope::from(&args.define); // 从命令行接收全部参数 | ||
|
||
// 读取参数`example.param1`,若未指定则使用默认值`1`. | ||
println!("param1={}", get_param!(example.param1, 1)); | ||
// 读取参数`example.param2`,在执行`<app> --help`时输出帮助信息. | ||
println!("param2={}", get_param!(example.param2, false, "help for example.param2")); | ||
} | ||
} | ||
``` | ||
当执行`clap_mini --help`时,在帮助信息结尾出现了`Hyperparameters`一节,说明了超参名称及其帮助信息: | ||
``` | ||
Usage: clap_mini [OPTIONS] | ||
Options: | ||
-D, --define <DEFINE> | ||
Specifies hyperparameters in the format `-D key=value` via the command line | ||
-h, --help | ||
Print help (see a summary with '-h') | ||
Hyperparameters: | ||
example.param2 | ||
help for example.param2 | ||
``` | ||
根据提示,可以使用`-D example.param2=<value>`来指定参数取值: | ||
```shell | ||
$ clap_mini # 默认取值 | ||
param1=1 | ||
param2=false | ||
|
||
$ clap_mini -D example.param2=true | ||
param1=1 | ||
param2=true | ||
``` | ||
|
||
## 结合配置文件使用 | ||
|
||
Hyperparameter 也支持与配置文件结合使用。以下示例展示了如何整合配置文件、命令行参数和用户自定义配置: | ||
|
||
```rust | ||
use std::path::Path; | ||
|
||
use clap::Parser; | ||
use config::{self, File}; | ||
use hyperparameter::*; | ||
|
||
#[derive(Parser)] | ||
#[command(after_long_help=generate_params_help())] | ||
struct CommandLineArgs { | ||
/// 在命令行以`-D key=value`格式指定参数 | ||
#[arg(short = 'D', long)] | ||
define: Vec<String>, | ||
|
||
/// 在命令行以`-C <path>`格式指定配置文件 | ||
#[arg(short = 'C', long, default_value = "examples/rust/cfg.toml")] | ||
config: String, | ||
} | ||
|
||
fn main() { | ||
let args = CommandLineArgs::parse(); | ||
let config_path = Path::new(&args.config); | ||
let config = config::Config::builder() | ||
.add_source(File::from(config_path)) | ||
.build().unwrap(); | ||
|
||
println!("param1={} // No scope", get_param!(example.param1, "default".to_string())); | ||
|
||
with_params! { // 配置文件参数作用域 | ||
params config.param_scope(); | ||
|
||
println!("param1={} // cfg file scope", get_param!(example.param1, "default".to_string())); | ||
with_params! { // 命令行参数作用域 | ||
params ParamScope::from(&args.define); | ||
|
||
println!("param1={} // cmdline args scope", get_param!(example.param1, "default".to_string(), "Example param1")); | ||
with_params! { // 用户自定义作用域 | ||
set example.param1= "scoped".to_string(); | ||
|
||
println!("param1={} // user-defined scope", get_param!(example.param1, "default".to_string())); | ||
} | ||
} | ||
} | ||
} | ||
|
||
``` | ||
直接执行命令`clap_layered`后得到如下输出: | ||
``` | ||
param1=default // No scope # 未进入任何scope | ||
param1=from config // cfg file scope # 进入配置文件scope,参数取值受配置文件影响 | ||
param1=from config // cmdline args scope # 进入命令行scope,命令行覆盖配置文件 | ||
param1=scoped // user-defined scope # 进入自定义scope,自定义取值覆盖命令行 | ||
``` | ||
可以看到: | ||
1. 嵌套的scope逐层覆盖,内层scope中参数覆盖外层scope; | ||
2. 命令行scope未指定参数,因此继承了外层scope的取值 | ||
|
||
若使用命令行指定`example.param1`的取值,则得到如下输入: | ||
```shell | ||
$ clap_layered -D example.param1="from cmdline" | ||
param1=default // No scope | ||
param1=from config // cfg file scope | ||
param1=from cmdline // cmdline args scope | ||
param1=scoped // user-defined scope | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
[example] | ||
param1 = "from config" |
Oops, something went wrong.