#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
pub enum TapError {
#[error("console {what} lock is poisoned")]
Poisoned {
what: &'static str,
},
#[error("tap station list refused: counted {named} stations, found {found}")]
StationsDisagree {
named: usize,
found: usize,
},
#[error("tap hop {hop} measured at {at_ms} ms, before the hop ahead of it at {before_ms} ms")]
HopsOutOfOrder {
hop: usize,
at_ms: u64,
before_ms: u64,
},
#[error("tap hop {hop} measured {early_ms} ms before first sight; left out")]
HopBeforeFirstSight {
hop: usize,
early_ms: u64,
},
#[error("tap hop {hop} measured beyond u64 milliseconds; left out")]
HopOverflow {
hop: usize,
},
#[error("tap observe failed {} ways: {}", .0.len(), display_all(.0))]
Several(Vec<Self>),
}
impl TapError {
#[must_use]
pub fn failures(&self) -> usize {
match self {
Self::Several(each) => each.len(),
_ => 1,
}
}
}
fn display_all(each: &[TapError]) -> String {
each.iter()
.map(ToString::to_string)
.collect::<Vec<_>>()
.join("; ")
}
pub fn lock<'a, T>(
mutex: &'a std::sync::Mutex<T>,
what: &'static str,
) -> Result<std::sync::MutexGuard<'a, T>, TapError> {
mutex.lock().map_err(|_| TapError::Poisoned { what })
}