use std::ops::ControlFlow;
use std::sync::Arc;
use super::{Advertisement, FetchError, FetchLimits, KnownHistory, ReceivedFetch, protocol};
use crate::packet::Wire;
pub struct DownloadedFetch {
#[cfg(feature = "tracing")]
pub(super) trace: crate::trace::DownloadContext,
pub(super) advertisement: Advertisement,
pub(super) negotiation: protocol::Negotiation,
pub(super) known: Option<Arc<KnownHistory>>,
pub(super) limits: FetchLimits,
pub(super) remaining: usize,
pub(super) body: Vec<u8>,
}
impl std::fmt::Debug for DownloadedFetch {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
f.debug_struct("DownloadedFetch")
.field("wire_bytes", &self.body.len())
.finish_non_exhaustive()
}
}
impl DownloadedFetch {
pub fn validate(
self,
cancel: &std::sync::atomic::AtomicBool,
progress: impl FnMut(&[u8]) -> ControlFlow<()>,
) -> Result<ReceivedFetch, FetchError> {
#[cfg(feature = "tracing")]
{
let context = self.trace.clone();
context.enter(|| self.validate_inner(cancel, progress))
}
#[cfg(not(feature = "tracing"))]
self.validate_inner(cancel, progress)
}
fn validate_inner(
self,
cancel: &std::sync::atomic::AtomicBool,
progress: impl FnMut(&[u8]) -> ControlFlow<()>,
) -> Result<ReceivedFetch, FetchError> {
#[cfg(feature = "tracing")]
let span = tracing::debug_span!(
target: "girt",
"fetch.validate",
outcome = "incomplete",
failure_class = tracing::field::Empty,
effects = tracing::field::Empty,
wire_bytes = self.body.len(),
);
let operation = || {
let empty = KnownHistory::default();
let history = self.known.as_deref().unwrap_or(&empty);
if !self.negotiation.needs_pack {
return ReceivedFetch::without_pack(
self.advertisement,
self.negotiation.wants,
history,
self.limits,
cancel,
);
}
let mut reader = self.body.as_slice();
let mut wire = Wire {
reader: &mut reader,
remaining: self.remaining,
cancel,
};
protocol::response(
&mut wire,
self.advertisement,
self.negotiation,
history,
self.limits,
cancel,
progress,
)
};
#[cfg(feature = "tracing")]
let result = span.in_scope(operation);
#[cfg(not(feature = "tracing"))]
let result = { operation }();
#[cfg(feature = "tracing")]
crate::trace::finish(&span, &result, crate::trace::fetch);
result
}
}