use std::{fmt, future::Future, pin::Pin};
use super::{ResolveError, ResolveReport};
use crate::SignedPacket;
type ResolveCompletion = Pin<Box<dyn Future<Output = ResolveOutcome> + Send + 'static>>;
pub struct ResolveResponse {
first: Option<SignedPacket>,
completion: ResolveCompletion,
}
impl ResolveResponse {
pub(crate) fn new(
first: Option<SignedPacket>,
completion: impl Future<Output = ResolveOutcome> + Send + 'static,
) -> Self {
Self {
first,
completion: Box::pin(completion),
}
}
pub fn first(&self) -> Option<&SignedPacket> {
self.first.as_ref()
}
pub async fn complete(self) -> ResolveOutcome {
self.completion.await
}
}
impl fmt::Debug for ResolveResponse {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
f.debug_struct("ResolveResponse")
.field("first", &self.first)
.finish_non_exhaustive()
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct ResolveOutcome {
pub most_recent: Result<SignedPacket, ResolveError>,
pub report: ResolveReport,
}
#[cfg(test)]
mod tests {
use super::*;
fn signed_packet() -> SignedPacket {
crate::SignedPacket::builder()
.address(
"_derp_region.iroh.".try_into().unwrap(),
"1.1.1.1".parse().unwrap(),
30,
)
.sign(&crate::Keypair::random())
.unwrap()
}
fn healthy_report() -> ResolveReport {
ResolveReport::new(mainline::GetMutableOutcome {
queried: 20,
values: 1,
no_values: 2,
no_more_recent: 0,
invalid_values: 0,
invalid_responses: 0,
krpc_errors: 0,
})
}
#[test]
fn resolve_response_exposes_first_packet() {
let first = signed_packet();
let response = ResolveResponse::new(Some(first.clone()), async move {
ResolveOutcome {
most_recent: Ok(signed_packet()),
report: healthy_report(),
}
});
assert_eq!(response.first(), Some(&first));
}
#[test]
fn resolve_response_completion_returns_resolve_outcome() {
let first = signed_packet();
let most_recent = signed_packet();
let report = healthy_report();
let expected_packet = most_recent.clone();
let expected_report = report.clone();
let response = ResolveResponse::new(Some(first), async move {
ResolveOutcome {
most_recent: Ok(most_recent),
report,
}
});
let resolved = futures_lite::future::block_on(response.complete());
assert_eq!(resolved.most_recent, Ok(expected_packet));
assert_eq!(resolved.report, expected_report);
}
}