use irontide_session::{TrackerInfo, TrackerStatus};
pub const PSEUDO_TRACKER_DHT_URL: &str = "** [DHT] **";
pub const PSEUDO_TRACKER_PEX_URL: &str = "** [PeX] **";
pub const PSEUDO_TRACKER_LSD_URL: &str = "** [LSD] **";
pub const PSEUDO_TRACKER_TIER: usize = usize::MAX;
#[must_use]
pub fn is_pseudo_tracker(t: &TrackerInfo) -> bool {
t.tier == PSEUDO_TRACKER_TIER
}
#[must_use]
pub fn synthesize_pseudo_trackers(
real: &[TrackerInfo],
dht_node_count: usize,
pex_peer_count: usize,
lsd_peer_count: usize,
) -> Vec<TrackerInfo> {
let mut out = Vec::with_capacity(real.len() + 3);
out.push(pseudo(PSEUDO_TRACKER_DHT_URL, dht_node_count));
out.push(pseudo(PSEUDO_TRACKER_PEX_URL, pex_peer_count));
out.push(pseudo(PSEUDO_TRACKER_LSD_URL, lsd_peer_count));
out.extend(real.iter().cloned());
out
}
#[allow(
clippy::cast_possible_truncation,
reason = "u32 saturation handled explicitly via min()"
)]
fn pseudo(url: &str, count: usize) -> TrackerInfo {
let count_u32 = count.min(u32::MAX as usize) as u32;
TrackerInfo {
url: url.to_string(),
tier: PSEUDO_TRACKER_TIER,
status: TrackerStatus::Working,
seeders: Some(count_u32),
leechers: None,
downloaded: None,
next_announce_secs: 0,
consecutive_failures: 0,
}
}
#[cfg(test)]
mod tests {
use super::*;
fn real_tracker(url: &str, tier: usize) -> TrackerInfo {
TrackerInfo {
url: url.to_string(),
tier,
status: TrackerStatus::NotContacted,
seeders: None,
leechers: None,
downloaded: None,
next_announce_secs: 0,
consecutive_failures: 0,
}
}
#[test]
fn three_pseudo_prepended_in_dht_pex_lsd_order() {
let result = synthesize_pseudo_trackers(&[], 0, 0, 0);
assert_eq!(result.len(), 3);
assert_eq!(result[0].url, PSEUDO_TRACKER_DHT_URL);
assert_eq!(result[1].url, PSEUDO_TRACKER_PEX_URL);
assert_eq!(result[2].url, PSEUDO_TRACKER_LSD_URL);
}
#[test]
fn pseudo_entries_all_use_sentinel_tier() {
let result = synthesize_pseudo_trackers(&[], 0, 0, 0);
for entry in result.iter().take(3) {
assert_eq!(entry.tier, PSEUDO_TRACKER_TIER);
assert!(is_pseudo_tracker(entry));
}
}
#[test]
fn counts_propagate_into_seeders_field() {
let result = synthesize_pseudo_trackers(&[], 42, 7, 3);
assert_eq!(result[0].seeders, Some(42));
assert_eq!(result[1].seeders, Some(7));
assert_eq!(result[2].seeders, Some(3));
for entry in &result {
assert_eq!(entry.leechers, None);
assert_eq!(entry.downloaded, None);
}
}
#[test]
fn dht_count_zero_still_renders_pseudo_row() {
let result = synthesize_pseudo_trackers(&[], 0, 5, 5);
assert_eq!(result[0].seeders, Some(0));
assert!(is_pseudo_tracker(&result[0]));
}
#[test]
fn real_trackers_appended_after_pseudo() {
let real = vec![
real_tracker("https://tracker.example/announce", 0),
real_tracker("https://backup.example/announce", 1),
];
let result = synthesize_pseudo_trackers(&real, 1, 1, 1);
assert_eq!(result.len(), 5);
assert_eq!(result[3].url, "https://tracker.example/announce");
assert_eq!(result[3].tier, 0);
assert!(!is_pseudo_tracker(&result[3]));
assert_eq!(result[4].tier, 1);
assert!(!is_pseudo_tracker(&result[4]));
}
#[test]
fn url_constants_match_qbt_wire_format() {
assert_eq!(PSEUDO_TRACKER_DHT_URL, "** [DHT] **");
assert_eq!(PSEUDO_TRACKER_PEX_URL, "** [PeX] **");
assert_eq!(PSEUDO_TRACKER_LSD_URL, "** [LSD] **");
}
}