Skip to main content

Config

Struct Config 

Source
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 settings
  • TestSelection — test execution controls
  • NetworkConfig — network and TLS settings
  • ServerSelection — server filtering options

Fields§

§output: OutputConfig

Output and display configuration

§test: TestSelection

Test execution controls

§network: NetworkConfig

Network and transport configuration

§servers: ServerSelection

Server selection criteria

§custom_user_agent: Option<String>

Custom user agent (file config only, not CLI)

§strict: bool

Strict validation mode

Implementations§

Source§

impl Config

Source

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 false
Source

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:

  1. Eliminates double file loading (file config passed directly)
  2. Returns a ValidationResult for reporting warnings/errors
  3. 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));
Source

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 when Some, file is the fallback, false when both are None.

  • Option<String> fields (e.g., ca_cert, tls_version): cli.or(file) — CLI wins, file is the fallback, None when both are absent.

  • u64 fields (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 30 always takes effect.

  • char fields (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));
Source

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);
}
Source

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());
Source

pub fn no_download(&self) -> bool

Whether to skip download test.

Source

pub fn no_upload(&self) -> bool

Whether to skip upload test.

Source

pub fn single(&self) -> bool

Whether to use single connection mode.

Source

pub fn bytes(&self) -> bool

Whether to display values in bytes instead of bits.

Source

pub fn simple(&self) -> bool

Whether to use simple output format.

Source

pub fn csv(&self) -> bool

Whether to output in CSV format.

Source

pub fn json(&self) -> bool

Whether to output in JSON format.

Source

pub fn quiet(&self) -> bool

Whether to suppress all progress output.

Source

pub fn list(&self) -> bool

Whether to display server list and exit.

Source

pub fn minimal(&self) -> bool

Whether to use minimal ASCII-only output.

Source

pub fn theme(&self) -> Theme

The color theme for terminal output.

Source

pub fn csv_delimiter(&self) -> char

The CSV field delimiter.

Source

pub fn csv_header(&self) -> bool

Whether to include CSV headers.

Source

pub fn profile(&self) -> Option<&str>

The user profile for customized output.

Source

pub fn format(&self) -> Option<Format>

The output format (supersedes legacy –json/–csv/–simple).

Source

pub fn timeout(&self) -> u64

The HTTP request timeout in seconds.

Source

pub fn source(&self) -> Option<&str>

The source IP address to bind to.

Source

pub fn ca_cert(&self) -> Option<&str>

Path to custom CA certificate for TLS.

Source

pub fn tls_version(&self) -> Option<&str>

Minimum TLS version (1.2 or 1.3).

Source

pub fn pin_certs(&self) -> bool

Whether speedtest.net/ookla.com TLS domain restriction is enabled.

Source

pub fn server_ids(&self) -> &[String]

Specific server IDs to use (empty = auto-select).

Source

pub fn exclude_ids(&self) -> &[String]

Server IDs to exclude from selection.

Source

pub fn custom_user_agent(&self) -> Option<&str>

Custom user agent string (file config only).

Source

pub fn strict(&self) -> bool

Whether strict validation mode is enabled.

Trait Implementations§

Source§

impl Clone for Config

Source§

fn clone(&self) -> Config

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl ConfigProvider for Config

Source§

fn config(&self) -> &Config

Source§

impl Debug for Config

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl Default for Config

Source§

fn default() -> Config

Returns the “default value” for a type. Read more
Source§

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.

Source§

fn from(config: &Config) -> Self

Converts to this type from the input type.

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<D> OwoColorize for D

Source§

fn fg<C>(&self) -> FgColorDisplay<'_, C, Self>
where C: Color,

Set the foreground color generically Read more
Source§

fn bg<C>(&self) -> BgColorDisplay<'_, C, Self>
where C: Color,

Set the background color generically. Read more
Source§

fn black(&self) -> FgColorDisplay<'_, Black, Self>

Change the foreground color to black
Source§

fn on_black(&self) -> BgColorDisplay<'_, Black, Self>

Change the background color to black
Source§

fn red(&self) -> FgColorDisplay<'_, Red, Self>

Change the foreground color to red
Source§

fn on_red(&self) -> BgColorDisplay<'_, Red, Self>

Change the background color to red
Source§

fn green(&self) -> FgColorDisplay<'_, Green, Self>

Change the foreground color to green
Source§

fn on_green(&self) -> BgColorDisplay<'_, Green, Self>

Change the background color to green
Source§

fn yellow(&self) -> FgColorDisplay<'_, Yellow, Self>

Change the foreground color to yellow
Source§

fn on_yellow(&self) -> BgColorDisplay<'_, Yellow, Self>

Change the background color to yellow
Source§

fn blue(&self) -> FgColorDisplay<'_, Blue, Self>

Change the foreground color to blue
Source§

fn on_blue(&self) -> BgColorDisplay<'_, Blue, Self>

Change the background color to blue
Source§

fn magenta(&self) -> FgColorDisplay<'_, Magenta, Self>

Change the foreground color to magenta
Source§

fn on_magenta(&self) -> BgColorDisplay<'_, Magenta, Self>

Change the background color to magenta
Source§

fn purple(&self) -> FgColorDisplay<'_, Magenta, Self>

Change the foreground color to purple
Source§

fn on_purple(&self) -> BgColorDisplay<'_, Magenta, Self>

Change the background color to purple
Source§

fn cyan(&self) -> FgColorDisplay<'_, Cyan, Self>

Change the foreground color to cyan
Source§

fn on_cyan(&self) -> BgColorDisplay<'_, Cyan, Self>

Change the background color to cyan
Source§

fn white(&self) -> FgColorDisplay<'_, White, Self>

Change the foreground color to white
Source§

fn on_white(&self) -> BgColorDisplay<'_, White, Self>

Change the background color to white
Source§

fn default_color(&self) -> FgColorDisplay<'_, Default, Self>

Change the foreground color to the terminal default
Source§

fn on_default_color(&self) -> BgColorDisplay<'_, Default, Self>

Change the background color to the terminal default
Source§

fn bright_black(&self) -> FgColorDisplay<'_, BrightBlack, Self>

Change the foreground color to bright black
Source§

fn on_bright_black(&self) -> BgColorDisplay<'_, BrightBlack, Self>

Change the background color to bright black
Source§

fn bright_red(&self) -> FgColorDisplay<'_, BrightRed, Self>

Change the foreground color to bright red
Source§

fn on_bright_red(&self) -> BgColorDisplay<'_, BrightRed, Self>

Change the background color to bright red
Source§

fn bright_green(&self) -> FgColorDisplay<'_, BrightGreen, Self>

Change the foreground color to bright green
Source§

fn on_bright_green(&self) -> BgColorDisplay<'_, BrightGreen, Self>

Change the background color to bright green
Source§

fn bright_yellow(&self) -> FgColorDisplay<'_, BrightYellow, Self>

Change the foreground color to bright yellow
Source§

fn on_bright_yellow(&self) -> BgColorDisplay<'_, BrightYellow, Self>

Change the background color to bright yellow
Source§

fn bright_blue(&self) -> FgColorDisplay<'_, BrightBlue, Self>

Change the foreground color to bright blue
Source§

fn on_bright_blue(&self) -> BgColorDisplay<'_, BrightBlue, Self>

Change the background color to bright blue
Source§

fn bright_magenta(&self) -> FgColorDisplay<'_, BrightMagenta, Self>

Change the foreground color to bright magenta
Source§

fn on_bright_magenta(&self) -> BgColorDisplay<'_, BrightMagenta, Self>

Change the background color to bright magenta
Source§

fn bright_purple(&self) -> FgColorDisplay<'_, BrightMagenta, Self>

Change the foreground color to bright purple
Source§

fn on_bright_purple(&self) -> BgColorDisplay<'_, BrightMagenta, Self>

Change the background color to bright purple
Source§

fn bright_cyan(&self) -> FgColorDisplay<'_, BrightCyan, Self>

Change the foreground color to bright cyan
Source§

fn on_bright_cyan(&self) -> BgColorDisplay<'_, BrightCyan, Self>

Change the background color to bright cyan
Source§

fn bright_white(&self) -> FgColorDisplay<'_, BrightWhite, Self>

Change the foreground color to bright white
Source§

fn on_bright_white(&self) -> BgColorDisplay<'_, BrightWhite, Self>

Change the background color to bright white
Source§

fn bold(&self) -> BoldDisplay<'_, Self>

Make the text bold
Source§

fn dimmed(&self) -> DimDisplay<'_, Self>

Make the text dim
Source§

fn italic(&self) -> ItalicDisplay<'_, Self>

Make the text italicized
Source§

fn underline(&self) -> UnderlineDisplay<'_, Self>

Make the text underlined
Make the text blink
Make the text blink (but fast!)
Source§

fn reversed(&self) -> ReversedDisplay<'_, Self>

Swap the foreground and background colors
Source§

fn hidden(&self) -> HiddenDisplay<'_, Self>

Hide the text
Source§

fn strikethrough(&self) -> StrikeThroughDisplay<'_, Self>

Cross out the text
Source§

fn color<Color>(&self, color: Color) -> FgDynColorDisplay<'_, Color, Self>
where Color: DynColor,

Set the foreground color at runtime. Only use if you do not know which color will be used at compile-time. If the color is constant, use either OwoColorize::fg or a color-specific method, such as OwoColorize::green, Read more
Source§

fn on_color<Color>(&self, color: Color) -> BgDynColorDisplay<'_, Color, Self>
where Color: DynColor,

Set the background color at runtime. Only use if you do not know what color to use at compile-time. If the color is constant, use either OwoColorize::bg or a color-specific method, such as OwoColorize::on_yellow, Read more
Source§

fn fg_rgb<const R: u8, const G: u8, const B: u8>( &self, ) -> FgColorDisplay<'_, CustomColor<R, G, B>, Self>

Set the foreground color to a specific RGB value.
Source§

fn bg_rgb<const R: u8, const G: u8, const B: u8>( &self, ) -> BgColorDisplay<'_, CustomColor<R, G, B>, Self>

Set the background color to a specific RGB value.
Source§

fn truecolor(&self, r: u8, g: u8, b: u8) -> FgDynColorDisplay<'_, Rgb, Self>

Sets the foreground color to an RGB value.
Source§

fn on_truecolor(&self, r: u8, g: u8, b: u8) -> BgDynColorDisplay<'_, Rgb, Self>

Sets the background color to an RGB value.
Source§

fn style(&self, style: Style) -> Styled<&Self>

Apply a runtime-determined style
Source§

impl<T> PolicyExt for T
where T: ?Sized,

Source§

fn and<P, B, E>(self, other: P) -> And<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow only if self and other return Action::Follow. Read more
Source§

fn or<P, B, E>(self, other: P) -> Or<T, P>
where T: Policy<B, E>, P: Policy<B, E>,

Create a new Policy that returns Action::Follow if either self or other returns Action::Follow. Read more
Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more