BandwidthFile

Struct BandwidthFile 

Source
pub struct BandwidthFile {
Show 20 fields pub timestamp: DateTime<Utc>, pub version: String, pub header: HashMap<String, String>, pub measurements: HashMap<String, BandwidthMeasurement>, pub software: Option<String>, pub software_version: Option<String>, pub earliest_bandwidth: Option<DateTime<Utc>>, pub latest_bandwidth: Option<DateTime<Utc>>, pub created_at: Option<DateTime<Utc>>, pub generated_at: Option<DateTime<Utc>>, pub consensus_size: Option<u32>, pub eligible_count: Option<u32>, pub eligible_percent: Option<u32>, pub min_count: Option<u32>, pub min_percent: Option<u32>, pub scanner_country: Option<String>, pub destinations_countries: Option<Vec<String>>, pub tor_version: Option<String>, pub time_to_report_half_network: Option<u32>, pub recent_stats: RecentStats, /* private fields */
}
Expand description

Tor bandwidth authority measurements file.

Bandwidth files contain relay bandwidth measurements collected by bandwidth scanners (like sbws) that measure the actual throughput of relays in the Tor network. Directory authorities use these measurements to assign bandwidth weights in the consensus, which affects how much traffic each relay receives.

§File Format Versions

The bandwidth file format has evolved over time:

VersionFeatures
1.0.0Basic format with timestamp and measurements only
1.1.0Added header section with metadata
1.2.0Added relay eligibility statistics
1.3.0Added scanner location information
1.4.0Added detailed measurement statistics

§Example

use stem_rs::descriptor::bandwidth_file::BandwidthFile;

let content = r#"1547487689
node_id=$221C91D4C51E4C73CB6A8F0BEE01B0A6BB4A8476 bw=38000 nick=myrelay"#;

let bw_file = BandwidthFile::parse(content)?;
assert_eq!(bw_file.version, "1.0.0");
assert_eq!(bw_file.measurements.len(), 1);

§See Also

Fields§

§timestamp: DateTime<Utc>

Unix timestamp when these metrics were published.

§version: String

Document format version (e.g., “1.0.0”, “1.4.0”).

Defaults to “1.0.0” if no version header is present.

§header: HashMap<String, String>

Raw header key-value pairs from the file.

Contains all header fields, including those parsed into dedicated fields.

§measurements: HashMap<String, BandwidthMeasurement>

Mapping of relay fingerprints to their bandwidth measurements.

Keys are 40-character hex fingerprints (without the $ prefix).

§software: Option<String>

Application that generated these metrics (e.g., “sbws”).

§software_version: Option<String>

Version of the application that generated these metrics.

§earliest_bandwidth: Option<DateTime<Utc>>

Time of the first bandwidth sampling in this file.

§latest_bandwidth: Option<DateTime<Utc>>

Time of the last bandwidth sampling in this file.

§created_at: Option<DateTime<Utc>>

Time when this file was created.

§generated_at: Option<DateTime<Utc>>

Time when collection of these metrics started.

§consensus_size: Option<u32>

Number of relays in the consensus at the time of measurement.

§eligible_count: Option<u32>

Number of relays with enough measurements to be included.

§eligible_percent: Option<u32>

Percentage of consensus relays with enough measurements.

§min_count: Option<u32>

Minimum number of eligible relays required for results to be provided.

§min_percent: Option<u32>

Minimum measured percentage of the consensus required.

§scanner_country: Option<String>

Two-letter country code where the scanner is located.

§destinations_countries: Option<Vec<String>>

List of country codes for all destinations that were scanned.

§tor_version: Option<String>

Tor version used by the scanner.

§time_to_report_half_network: Option<u32>

Estimated seconds required to measure half the network.

Based on recent measurement rates.

§recent_stats: RecentStats

Statistical information collected over the recent data period.

Typically covers the last five days of measurements.

Implementations§

Source§

impl BandwidthFile

Source

pub fn parse(content: &str) -> Result<Self, Error>

Parses a bandwidth file from its string content.

§Format

The file format consists of:

  1. A Unix timestamp on the first line
  2. Optional header key-value pairs (version 1.1.0+)
  3. A divider line (===== or ====)
  4. Measurement lines with relay bandwidth data
§Arguments
  • content - The raw bandwidth file content as a string
§Errors

Returns Error::Parse if:

  • The file is empty
  • The first line is not a valid Unix timestamp
  • The version header is not in the second position (if present)
  • A relay fingerprint appears multiple times
§Example
use stem_rs::descriptor::bandwidth_file::BandwidthFile;

// Version 1.0.0 format (no headers)
let v1_content = "1547487689\nnode_id=$ABC123 bw=1000";
let bw = BandwidthFile::parse(v1_content)?;
assert_eq!(bw.version, "1.0.0");

// Version 1.2.0+ format (with headers)
let v1_2_content = r#"1547487689
version=1.2.0
software=sbws
=====
node_id=$ABC123 bw=1000"#;
let bw = BandwidthFile::parse(v1_2_content)?;
assert_eq!(bw.version, "1.2.0");
Source

pub fn raw_content(&self) -> &[u8]

Returns the raw bytes of the original bandwidth file content.

This preserves the exact content as it was parsed, which can be useful for signature verification or debugging.

Source

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

Returns lines from the measurement body that could not be parsed.

Lines are considered unrecognized if they don’t contain a valid node_id field. This can happen with malformed entries or future format extensions.

Source

pub fn to_descriptor_string(&self) -> String

Serializes the bandwidth file back to its string representation.

The output format depends on the version:

  • Version 1.0.0: Just timestamp and measurements
  • Version 1.1.0+: Includes header section with divider
§Note

The output may not be byte-for-byte identical to the original input due to field ordering and formatting differences.

Trait Implementations§

Source§

impl Clone for BandwidthFile

Source§

fn clone(&self) -> BandwidthFile

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 Debug for BandwidthFile

Source§

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

Formats the value using the given formatter. Read more

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, 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<T> Same for T

Source§

type Output = T

Should always be Self
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.