pub struct Config {
pub output: OutputConfig,
pub test: TestSelection,
pub network: NetworkConfig,
pub servers: ServerSelection,
pub custom_user_agent: Option<String>,
pub strict: bool,
}Expand description
Main configuration struct composed of semantic sub-structs.
Groups related configuration into cohesive units for better code organization:
OutputConfig— output and display settingsTestSelection— test execution controlsNetworkConfig— network and TLS settingsServerSelection— server filtering options
Fields§
§output: OutputConfigOutput and display configuration
test: TestSelectionTest execution controls
network: NetworkConfigNetwork and transport configuration
servers: ServerSelectionServer selection criteria
custom_user_agent: Option<String>Custom user agent (file config only, not CLI)
strict: boolStrict validation mode
Implementations§
Source§impl Config
impl Config
Sourcepub fn from_args(args: &Args) -> Self
pub fn from_args(args: &Args) -> Self
Build configuration from parsed CLI arguments and the config file.
Converts Args into ConfigSource first (the sole CLI→config bridge),
then builds sub-structs from the source abstraction.
Note: This method does NOT call validate_and_report().
For validation with warnings/errors, use
from_args_with_file() instead, which also
avoids loading the config file twice.
§Example
use clap::Parser;
use netspeed_cli::cli::Args;
use netspeed_cli::config::{Config, Format};
// Parse CLI arguments (same as the main entry point)
let args = Args::parse_from(["netspeed-cli", "--format", "json", "--timeout", "30"]);
let config = Config::from_args(&args);
assert_eq!(config.timeout(), 30);
assert_eq!(config.format(), Some(Format::Json));
assert!(!config.no_download()); // unset flags default to falseSourcepub fn from_args_with_file(
source: &ConfigSource,
file_config: Option<File>,
) -> (Self, ValidationResult)
pub fn from_args_with_file( source: &ConfigSource, file_config: Option<File>, ) -> (Self, ValidationResult)
Build configuration from parsed CLI arguments with a pre-loaded config file.
This is the preferred constructor in production code because it:
- Eliminates double file loading (file config passed directly)
- Returns a
ValidationResultfor reporting warnings/errors - Does NOT print or exit — callers control error handling
For test code that doesn’t need validation, use
from_source() with a hand-built ConfigSource.
§Example
use clap::Parser;
use netspeed_cli::cli::Args;
use netspeed_cli::config::{Config, ConfigSource, ValidationResult};
// Parse CLI arguments and convert to ConfigSource
let args = Args::parse_from(["netspeed-cli", "--format", "json"]);
let source = ConfigSource::from_args(&args);
// Load config file (or pass None for defaults)
let file_config = netspeed_cli::config::load_config_file();
// Build config with validation results
let (config, validation) = Config::from_args_with_file(&source, file_config);
// Handle validation results
for warning in &validation.warnings {
eprintln!("Warning: {warning}");
}
// Continue with config...
assert_eq!(config.format(), Some(netspeed_cli::config::Format::Json));Sourcepub fn from_source(source: &ConfigSource) -> Self
pub fn from_source(source: &ConfigSource) -> Self
Build configuration from a ConfigSource and the config file.
This constructor operates entirely within the config layer — no
dependency on crate::cli::Args. Exposed as pub so that
external test crates can construct a Config from a hand-built
ConfigSource without going through CLI parsing.
Side-effect free: This method does NOT print to stderr or exit.
Call Config::validate_and_report() separately
to emit validation warnings/errors, or use
Config::from_args_with_file() which handles
validation automatically.
§Merge Strategy
Values are resolved with CLI > file > hardcoded defaults priority:
-
Option<bool>fields (e.g.,bytes,no_download):cli.or(file).unwrap_or(false)— CLI wins whenSome, file is the fallback,falsewhen both areNone. -
Option<String>fields (e.g.,ca_cert,tls_version):cli.or(file)— CLI wins, file is the fallback,Nonewhen both are absent. -
u64fields (e.g.,timeout): If the CLI value equals the hardcoded default, the file value is tried first; otherwise the CLI value wins. This lets--timeout 10(the default) fall through to the file config while an explicit--timeout 30always takes effect. -
charfields (e.g.,csv_delimiter): If the CLI value equals the hardcoded default (,), the file value is used; otherwise the CLI value wins.
§Example
External crates can build a Config without CLI parsing by
constructing a ConfigSource from its sub-source structs:
use netspeed_cli::config::{
Config, ConfigSource, Format, NetworkSource, OutputSource,
};
let source = ConfigSource {
output: OutputSource {
format: Some(Format::Json),
quiet: Some(true),
..Default::default()
},
network: NetworkSource {
timeout: 30,
..Default::default()
},
..Default::default()
};
let config = Config::from_source(&source);
assert_eq!(config.timeout(), 30);
assert_eq!(config.format(), Some(Format::Json));Sourcepub fn validate_and_report(
&self,
source: &ConfigSource,
file_config: Option<File>,
) -> ValidationResult
pub fn validate_and_report( &self, source: &ConfigSource, file_config: Option<File>, ) -> ValidationResult
Validate configuration and emit warnings/errors.
This method handles the side effects that were removed from
from_source(): printing validation errors/warnings
and exiting in strict mode. Call this after building config from CLI args.
Returns the ValidationResult so callers can decide how to handle
failures (e.g., exit in strict mode, log in normal mode).
§Example
use netspeed_cli::config::{Config, ConfigSource};
let source = ConfigSource::default();
let config = Config::from_source(&source);
// Emit validation warnings/errors
let result = config.validate_and_report(&source, None);
for error in &result.errors {
eprintln!("Error: {error}");
}
for warning in &result.warnings {
eprintln!("Warning: {warning}");
}
// Exit if strict mode and validation failed
if config.strict() && !result.valid {
std::process::exit(1);
}Sourcepub fn should_save_history(&self) -> bool
pub fn should_save_history(&self) -> bool
Whether test results should be saved to history.
Machine-readable formats (JSON, JSONL, CSV) corrupt stdout when mixed with history output, so we skip saving in those cases.
§Example
use netspeed_cli::config::Config;
let config = Config::default();
// Default format is Detailed → should save history
assert!(config.should_save_history());Sourcepub fn no_download(&self) -> bool
pub fn no_download(&self) -> bool
Whether to skip download test.
Sourcepub fn csv_delimiter(&self) -> char
pub fn csv_delimiter(&self) -> char
The CSV field delimiter.
Sourcepub fn csv_header(&self) -> bool
pub fn csv_header(&self) -> bool
Whether to include CSV headers.
Sourcepub fn format(&self) -> Option<Format>
pub fn format(&self) -> Option<Format>
The output format (supersedes legacy –json/–csv/–simple).
Sourcepub fn tls_version(&self) -> Option<&str>
pub fn tls_version(&self) -> Option<&str>
Minimum TLS version (1.2 or 1.3).
Sourcepub fn pin_certs(&self) -> bool
pub fn pin_certs(&self) -> bool
Whether speedtest.net/ookla.com TLS domain restriction is enabled.
Sourcepub fn server_ids(&self) -> &[String]
pub fn server_ids(&self) -> &[String]
Specific server IDs to use (empty = auto-select).
Sourcepub fn exclude_ids(&self) -> &[String]
pub fn exclude_ids(&self) -> &[String]
Server IDs to exclude from selection.
Sourcepub fn custom_user_agent(&self) -> Option<&str>
pub fn custom_user_agent(&self) -> Option<&str>
Custom user agent string (file config only).
Trait Implementations§
Source§impl From<&Config> for Settings
Build Settings from a crate::config::Config reference.
impl From<&Config> for Settings
Build Settings from a crate::config::Config reference.
Centralizes the Config→HTTP bridging so callers don’t duplicate the mapping. Resolves custom_user_agent from file config or default.
This impl lives in http.rs (not config.rs) to preserve layering:
dependency flows http → config, not config → http.
Auto Trait Implementations§
impl Freeze for Config
impl RefUnwindSafe for Config
impl Send for Config
impl Sync for Config
impl Unpin for Config
impl UnsafeUnpin for Config
impl UnwindSafe for Config
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> Instrument for T
impl<T> Instrument for T
Source§fn instrument(self, span: Span) -> Instrumented<Self>
fn instrument(self, span: Span) -> Instrumented<Self>
Source§fn in_current_span(self) -> Instrumented<Self>
fn in_current_span(self) -> Instrumented<Self>
Source§impl<D> OwoColorize for D
impl<D> OwoColorize for D
Source§fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>where
C: Color,
Source§fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>where
C: Color,
Source§fn black(&self) -> FgColorDisplay<'_, Black, Self>
fn black(&self) -> FgColorDisplay<'_, Black, Self>
Source§fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
fn on_black(&self) -> BgColorDisplay<'_, Black, Self>
Source§fn red(&self) -> FgColorDisplay<'_, Red, Self>
fn red(&self) -> FgColorDisplay<'_, Red, Self>
Source§fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
fn on_red(&self) -> BgColorDisplay<'_, Red, Self>
Source§fn green(&self) -> FgColorDisplay<'_, Green, Self>
fn green(&self) -> FgColorDisplay<'_, Green, Self>
Source§fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
fn on_green(&self) -> BgColorDisplay<'_, Green, Self>
Source§fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>
Source§fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>
Source§fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
fn blue(&self) -> FgColorDisplay<'_, Blue, Self>
Source§fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>
Source§fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>
Source§fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>
Source§fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>
Source§fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>
Source§fn white(&self) -> FgColorDisplay<'_, White, Self>
fn white(&self) -> FgColorDisplay<'_, White, Self>
Source§fn on_white(&self) -> BgColorDisplay<'_, White, Self>
fn on_white(&self) -> BgColorDisplay<'_, White, Self>
Source§fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
fn default_color(&self) -> FgColorDisplay<'_, Default, Self>
Source§fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>
Source§fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>
Source§fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>
Source§fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>
Source§fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>
Source§fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>
Source§fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>
Source§fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>
Source§fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>
Source§fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>
Source§fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>
Source§fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>
Source§fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>
Source§fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>
Source§fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>
Source§fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>
Source§fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>
Source§fn bold(&self) -> BoldDisplay<'_, Self>
fn bold(&self) -> BoldDisplay<'_, Self>
Source§fn dimmed(&self) -> DimDisplay<'_, Self>
fn dimmed(&self) -> DimDisplay<'_, Self>
Source§fn italic(&self) -> ItalicDisplay<'_, Self>
fn italic(&self) -> ItalicDisplay<'_, Self>
Source§fn underline(&self) -> UnderlineDisplay<'_, Self>
fn underline(&self) -> UnderlineDisplay<'_, Self>
Source§fn blink(&self) -> BlinkDisplay<'_, Self>
fn blink(&self) -> BlinkDisplay<'_, Self>
Source§fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
fn blink_fast(&self) -> BlinkFastDisplay<'_, Self>
Source§fn reversed(&self) -> ReversedDisplay<'_, Self>
fn reversed(&self) -> ReversedDisplay<'_, Self>
Source§fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>
Source§fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::fg or
a color-specific method, such as OwoColorize::green, Read moreSource§fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>where
Color: DynColor,
OwoColorize::bg or
a color-specific method, such as OwoColorize::on_yellow, Read more