use mainline::errors::PutMutableError;
use super::ResolveReport;
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, Hash)]
pub enum PublishError {
#[error("DHT query timed out")]
Timeout,
#[error("DHT query found no closest nodes")]
NoClosestNodes,
#[error("DHT query returned error response code: {code}, description: {description}")]
ErrorResponse {
code: i32,
description: String,
},
#[error("packet is not the most recent")]
NotMostRecent,
}
impl From<PutMutableError> for PublishError {
fn from(value: PutMutableError) -> Self {
match value {
PutMutableError::Query(error) => match error {
mainline::errors::PutQueryError::Timeout => PublishError::Timeout,
mainline::errors::PutQueryError::NoClosestNodes => PublishError::NoClosestNodes,
mainline::errors::PutQueryError::ErrorResponse(error) => {
PublishError::ErrorResponse {
code: error.code,
description: error.description,
}
}
},
PutMutableError::Concurrency(_) => PublishError::NotMostRecent,
}
}
}
#[derive(thiserror::Error, Debug, Clone, PartialEq, Eq, Hash)]
pub enum ResolveError {
#[error("no DHT nodes were queried")]
NoNodesQueried,
#[error("no queried DHT nodes responded")]
NoNodesResponded,
#[error("no responded DHT nodes returned usable response")]
NoUsableResponses,
#[error("signed packet not found")]
NotFound,
#[error("DHT mutable item at seq {seq} is not a valid signed packet")]
InvalidSignedPacket {
seq: i64,
},
}
impl From<ResolveReport> for ResolveError {
fn from(report: ResolveReport) -> Self {
if report.queried() == 0 {
Self::NoNodesQueried
} else if report.responded() == 0 {
Self::NoNodesResponded
} else if report.usable_responses() == 0 {
Self::NoUsableResponses
} else {
Self::NotFound
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn report(outcome: mainline::GetMutableOutcome) -> ResolveReport {
ResolveReport::new(outcome)
}
#[test]
fn resolve_report_without_queried_nodes_maps_to_no_nodes_queried() {
let error = ResolveError::from(report(mainline::GetMutableOutcome::default()));
assert_eq!(error, ResolveError::NoNodesQueried);
}
#[test]
fn resolve_report_without_responses_maps_to_no_nodes_responded() {
let error = ResolveError::from(report(mainline::GetMutableOutcome {
queried: 20,
..Default::default()
}));
assert_eq!(error, ResolveError::NoNodesResponded);
}
#[test]
fn resolve_report_without_usable_responses_maps_to_no_usable_responses() {
let error = ResolveError::from(report(mainline::GetMutableOutcome {
queried: 20,
invalid_responses: 1,
..Default::default()
}));
assert_eq!(error, ResolveError::NoUsableResponses);
}
#[test]
fn resolve_report_with_usable_responses_maps_to_not_found() {
let error = ResolveError::from(report(mainline::GetMutableOutcome {
queried: 20,
no_values: 1,
..Default::default()
}));
assert_eq!(error, ResolveError::NotFound);
}
}