mirror of
https://github.com/kristoferssolo/tls-pq-bench.git
synced 2026-03-22 00:36:21 +00:00
refactor(runner): reorganize config module
This commit is contained in:
85
runner/src/config/mod.rs
Normal file
85
runner/src/config/mod.rs
Normal file
@@ -0,0 +1,85 @@
|
|||||||
|
mod utils;
|
||||||
|
|
||||||
|
use crate::{
|
||||||
|
args::Args,
|
||||||
|
config::utils::validate_config,
|
||||||
|
error::{self, ConfigError},
|
||||||
|
};
|
||||||
|
use common::{self, KeyExchangeMode};
|
||||||
|
use miette::{NamedSource, SourceSpan};
|
||||||
|
use serde::Deserialize;
|
||||||
|
use std::{fs::read_to_string, net::SocketAddr, path::Path};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct BenchmarkConfig {
|
||||||
|
pub mode: String,
|
||||||
|
pub payload: u32,
|
||||||
|
pub iters: u32,
|
||||||
|
pub warmup: u32,
|
||||||
|
pub concurrency: u32,
|
||||||
|
pub server: SocketAddr,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Deserialize)]
|
||||||
|
pub struct Config {
|
||||||
|
pub benchmarks: Vec<BenchmarkConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Load benchmark configuration from a TOML file.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// Returns an error if the file cannot be read or parsed.
|
||||||
|
pub fn load_from_file(path: &Path) -> error::Result<Config> {
|
||||||
|
let content = read_to_string(path).map_err(|source| ConfigError::ReadError {
|
||||||
|
source,
|
||||||
|
path: path.to_owned(),
|
||||||
|
})?;
|
||||||
|
|
||||||
|
let src = NamedSource::new(path.display().to_string(), content.clone());
|
||||||
|
|
||||||
|
let config = toml::from_str::<Config>(&content).map_err(|source| {
|
||||||
|
let span = source
|
||||||
|
.span()
|
||||||
|
.map(|s| SourceSpan::new(s.start.into(), s.end - s.start));
|
||||||
|
|
||||||
|
ConfigError::TomlParseError {
|
||||||
|
src: src.clone(),
|
||||||
|
span,
|
||||||
|
source,
|
||||||
|
}
|
||||||
|
})?;
|
||||||
|
|
||||||
|
validate_config(&config, &content, path)?;
|
||||||
|
|
||||||
|
Ok(config)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create benchmark configuration from CLI arguments.
|
||||||
|
///
|
||||||
|
/// # Errors
|
||||||
|
/// Never returns an error, but returns Result for consistency.
|
||||||
|
pub fn load_from_cli(args: &Args) -> error::Result<Config> {
|
||||||
|
Ok(Config {
|
||||||
|
benchmarks: vec![BenchmarkConfig {
|
||||||
|
mode: args.mode.to_string(),
|
||||||
|
payload: args.payload_bytes,
|
||||||
|
iters: args.iters,
|
||||||
|
warmup: args.warmup,
|
||||||
|
concurrency: args.concurrency,
|
||||||
|
server: args
|
||||||
|
.server
|
||||||
|
.ok_or_else(|| common::Error::config("--server ir required"))?,
|
||||||
|
}],
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Config {
|
||||||
|
/// Get the key exchange mode from the first benchmark configuration.
|
||||||
|
#[must_use]
|
||||||
|
pub fn server_mode(&self) -> KeyExchangeMode {
|
||||||
|
self.benchmarks
|
||||||
|
.first()
|
||||||
|
.and_then(|b| b.mode.parse().ok())
|
||||||
|
.unwrap_or(KeyExchangeMode::X25519)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,88 +1,13 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
args::Args,
|
config::{BenchmarkConfig, Config},
|
||||||
error::{self, ConfigError},
|
error::{self, ConfigError},
|
||||||
};
|
};
|
||||||
use common::{self, KeyExchangeMode};
|
use common::{self, KeyExchangeMode};
|
||||||
use miette::{NamedSource, SourceSpan};
|
use miette::{NamedSource, SourceSpan};
|
||||||
use serde::Deserialize;
|
use std::path::Path;
|
||||||
use std::{fs::read_to_string, net::SocketAddr, path::Path};
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
|
||||||
pub struct BenchmarkConfig {
|
|
||||||
pub mode: String,
|
|
||||||
pub payload: u32,
|
|
||||||
pub iters: u32,
|
|
||||||
pub warmup: u32,
|
|
||||||
pub concurrency: u32,
|
|
||||||
pub server: SocketAddr,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, Deserialize)]
|
|
||||||
pub struct Config {
|
|
||||||
pub benchmarks: Vec<BenchmarkConfig>,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Load benchmark configuration from a TOML file.
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// Returns an error if the file cannot be read or parsed.
|
|
||||||
pub fn load_from_file(path: &Path) -> error::Result<Config> {
|
|
||||||
let content = read_to_string(path).map_err(|source| ConfigError::ReadError {
|
|
||||||
source,
|
|
||||||
path: path.to_owned(),
|
|
||||||
})?;
|
|
||||||
|
|
||||||
let src = NamedSource::new(path.display().to_string(), content.clone());
|
|
||||||
|
|
||||||
let config = toml::from_str::<Config>(&content).map_err(|source| {
|
|
||||||
let span = source
|
|
||||||
.span()
|
|
||||||
.map(|s| SourceSpan::new(s.start.into(), s.end - s.start));
|
|
||||||
|
|
||||||
ConfigError::TomlParseError {
|
|
||||||
src: src.clone(),
|
|
||||||
span,
|
|
||||||
source,
|
|
||||||
}
|
|
||||||
})?;
|
|
||||||
|
|
||||||
validate_config(&config, &content, path)?;
|
|
||||||
|
|
||||||
Ok(config)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create benchmark configuration from CLI arguments.
|
|
||||||
///
|
|
||||||
/// # Errors
|
|
||||||
/// Never returns an error, but returns Result for consistency.
|
|
||||||
pub fn load_from_cli(args: &Args) -> error::Result<Config> {
|
|
||||||
Ok(Config {
|
|
||||||
benchmarks: vec![BenchmarkConfig {
|
|
||||||
mode: args.mode.to_string(),
|
|
||||||
payload: args.payload_bytes,
|
|
||||||
iters: args.iters,
|
|
||||||
warmup: args.warmup,
|
|
||||||
concurrency: args.concurrency,
|
|
||||||
server: args
|
|
||||||
.server
|
|
||||||
.ok_or_else(|| common::Error::config("--server ir required"))?,
|
|
||||||
}],
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Config {
|
|
||||||
/// Get the key exchange mode from the first benchmark configuration.
|
|
||||||
#[must_use]
|
|
||||||
pub fn server_mode(&self) -> KeyExchangeMode {
|
|
||||||
self.benchmarks
|
|
||||||
.first()
|
|
||||||
.and_then(|b| b.mode.parse().ok())
|
|
||||||
.unwrap_or(KeyExchangeMode::X25519)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Validate the configuration after parsing.
|
/// Validate the configuration after parsing.
|
||||||
fn validate_config(config: &Config, content: &str, path: &Path) -> error::Result<()> {
|
pub fn validate_config(config: &Config, content: &str, path: &Path) -> error::Result<()> {
|
||||||
if config.benchmarks.is_empty() {
|
if config.benchmarks.is_empty() {
|
||||||
return Err(ConfigError::EmptyBenchmarks {
|
return Err(ConfigError::EmptyBenchmarks {
|
||||||
src: NamedSource::new(path.display().to_string(), content.to_string()),
|
src: NamedSource::new(path.display().to_string(), content.to_string()),
|
||||||
@@ -121,39 +46,30 @@ fn validate_benchmark(
|
|||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if benchmark.payload == 0 {
|
validate_positive_field(src.clone(), content, idx, "payload", benchmark.payload)?;
|
||||||
|
validate_positive_field(src.clone(), content, idx, "iters", benchmark.iters)?;
|
||||||
|
validate_positive_field(src, content, idx, "concurrency", benchmark.concurrency)?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn validate_positive_field(
|
||||||
|
src: NamedSource<String>,
|
||||||
|
content: &str,
|
||||||
|
idx: usize,
|
||||||
|
field_name: &str,
|
||||||
|
value: u32,
|
||||||
|
) -> error::Result<()> {
|
||||||
|
if value == 0 {
|
||||||
return Err(ConfigError::ValidationError {
|
return Err(ConfigError::ValidationError {
|
||||||
src,
|
src,
|
||||||
span: find_field_span(content, idx, "payload"),
|
span: find_field_span(content, idx, field_name),
|
||||||
field: "payload".into(),
|
field: field_name.into(),
|
||||||
idx,
|
idx,
|
||||||
message: "Must be greater than 0".into(),
|
message: "Must be greater than 0".into(),
|
||||||
}
|
}
|
||||||
.into());
|
.into());
|
||||||
}
|
}
|
||||||
|
|
||||||
if benchmark.iters == 0 {
|
|
||||||
return Err(ConfigError::ValidationError {
|
|
||||||
src,
|
|
||||||
span: find_field_span(content, idx, "iters"),
|
|
||||||
field: "iters".into(),
|
|
||||||
idx,
|
|
||||||
message: "Must be greater than 0".into(),
|
|
||||||
}
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
if benchmark.concurrency == 0 {
|
|
||||||
return Err(ConfigError::ValidationError {
|
|
||||||
src,
|
|
||||||
span: find_field_span(content, idx, "concurrency"),
|
|
||||||
field: "concurrency".into(),
|
|
||||||
idx,
|
|
||||||
message: "Must be greater than 0".into(),
|
|
||||||
}
|
|
||||||
.into());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
Reference in New Issue
Block a user