qubit-fs 0.2.2

Provider-neutral synchronous and asynchronous filesystem abstraction for Rust
Documentation
// =============================================================================
//    Copyright (c) 2026 Haixing Hu.
//
//    SPDX-License-Identifier: Apache-2.0
//
//    Licensed under the Apache License, Version 2.0.
// =============================================================================
// facade.
//! Provider copy failure facts.

use crate::copy::CopyFailureState;
use crate::copy::CopyStats;
use crate::error::FsError;

/// Typed provider copy failure reserved for copy orchestration.
///
/// # Examples
///
/// ```rust
/// use qubit_fs::copy::CopyFailureState;
/// use qubit_fs::copy::CopyStats;
/// use qubit_fs::error::{FsError, FsErrorKind, FsOperation};
/// use qubit_fs::spi::SpiCopyFailure;
///
/// let failure = SpiCopyFailure::new(
///     FsError::new(FsErrorKind::Io, FsOperation::Copy, "failed"),
///     CopyFailureState::Unchanged,
///     CopyStats::default(),
/// );
/// assert_eq!(CopyFailureState::Unchanged, failure.state());
/// ```
pub struct SpiCopyFailure {
    /// Provider failure with filesystem context.
    error: Box<FsError>,
    /// Provider-confirmed destination publication state.
    state: CopyFailureState,
    /// Transfer progress confirmed before failure.
    partial_stats: CopyStats,
}

impl SpiCopyFailure {
    /// Creates a typed provider copy failure.
    ///
    /// # Parameters
    /// - `error`: Provider failure with filesystem context.
    /// - `state`: Provider-confirmed publication state.
    /// - `partial_stats`: Transfer progress confirmed before failure.
    ///
    /// # Returns
    /// A failure containing all provider-confirmed facts.
    #[inline]
    #[must_use]
    pub fn new(error: FsError, state: CopyFailureState, partial_stats: CopyStats) -> Self {
        Self {
            error: Box::new(error),
            state,
            partial_stats,
        }
    }

    /// Returns the provider error without exposing a recovery writer.
    ///
    /// # Returns
    /// The provider failure with filesystem context.
    #[inline]
    #[must_use]
    pub fn error(&self) -> &FsError {
        &self.error
    }

    /// Returns the typed publication state.
    ///
    /// # Returns
    /// The provider-confirmed publication state.
    #[inline]
    #[must_use]
    pub const fn state(&self) -> CopyFailureState {
        self.state
    }

    /// Splits this failure into its typed facts.
    ///
    /// # Returns
    /// The provider error, publication state, and partial transfer statistics.
    #[inline]
    #[must_use]
    pub fn into_parts(self) -> (FsError, CopyFailureState, CopyStats) {
        (*self.error, self.state, self.partial_stats)
    }
}

#[cfg(test)]
mod tests {
    use super::SpiCopyFailure;
    use crate::copy::CopyFailureState;
    use crate::copy::CopyStats;
    use crate::error::FsError;
    use crate::error::FsErrorKind;
    use crate::error::FsOperation;

    #[test]
    fn failure_facts_are_executed_at_runtime() {
        let failure = SpiCopyFailure::new(
            FsError::new(FsErrorKind::NotFound, FsOperation::Copy, "missing source"),
            CopyFailureState::PartiallyPublished,
            CopyStats {
                bytes: 4,
                ..CopyStats::default()
            },
        );
        assert_eq!(failure.error().kind(), FsErrorKind::NotFound);
        assert_eq!(failure.state(), CopyFailureState::PartiallyPublished);

        let (error, state, stats) = failure.into_parts();
        assert_eq!(error.kind(), FsErrorKind::NotFound);
        assert_eq!(state, CopyFailureState::PartiallyPublished);
        assert_eq!(stats.bytes, 4);
    }
}