use crate::copy::AsyncCopyFailure;
use crate::copy::AsyncCopyOperationState;
use crate::copy::CopyFailureState;
use crate::copy::CopyOutcome;
use crate::copy::CopyStats;
use crate::copy::internal::CopyRecoverySnapshot;
use crate::write::AsyncWriterRecovery;
pub(in crate::copy) struct CopyCancellationGuard<'a> {
state: &'a mut AsyncCopyOperationState,
writer: &'a mut Option<AsyncWriterRecovery>,
recovery: &'a mut CopyRecoverySnapshot,
finished: bool,
}
impl<'a> CopyCancellationGuard<'a> {
#[inline]
pub(in crate::copy) fn start(
state: &'a mut AsyncCopyOperationState,
writer: &'a mut Option<AsyncWriterRecovery>,
recovery: &'a mut CopyRecoverySnapshot,
) -> Self {
*state = AsyncCopyOperationState::Running;
Self {
state,
writer,
recovery,
finished: false,
}
}
#[inline]
pub(in crate::copy) fn writer_mut(&mut self) -> &mut Option<AsyncWriterRecovery> {
self.writer
}
#[inline]
pub(in crate::copy) fn finish(&mut self, result: &Result<CopyOutcome, AsyncCopyFailure>) {
*self.state = match result {
Ok(outcome) => {
self.recovery.state = CopyFailureState::Published;
self.recovery.stats = *outcome.stats();
AsyncCopyOperationState::Completed
}
Err(failure) => {
self.recovery.state = failure.state();
self.recovery.stats = *failure.partial_stats();
AsyncCopyOperationState::Failed(failure.state())
}
};
self.finished = true;
}
}
impl Drop for CopyCancellationGuard<'_> {
fn drop(&mut self) {
if !self.finished && *self.state == AsyncCopyOperationState::Running {
*self.state = AsyncCopyOperationState::Failed(CopyFailureState::Indeterminate);
self.recovery.state = CopyFailureState::Indeterminate;
self.recovery.stats = self
.writer
.as_ref()
.and_then(AsyncWriterRecovery::opened)
.map_or(CopyStats::default(), |writer| {
crate::copy::internal::fallback_failure_stats(writer.written_bytes())
});
if let Some(writer) = self.writer.as_mut().and_then(AsyncWriterRecovery::opened_mut) {
writer.mark_indeterminate();
}
}
}
}