qubit_fs/copy/
copy_failure.rs1use std::error::Error;
12use std::fmt::Debug;
13use std::fmt::Display;
14use std::fmt::Formatter;
15use std::fmt::Result as FmtResult;
16
17use crate::copy::CopyFailureState;
18use crate::copy::CopyStats;
19use crate::copy::internal::CopyFailureParts;
20use crate::error::FsError;
21use crate::write::WriterRecovery;
22
23pub struct CopyFailure {
47 parts: Box<CopyFailureParts>,
49}
50impl CopyFailure {
51 #[must_use]
53 pub(crate) fn new(
54 error: FsError,
55 state: CopyFailureState,
56 partial_stats: CopyStats,
57 writer: Option<WriterRecovery>,
58 ) -> Self {
59 Self {
60 parts: Box::new(CopyFailureParts {
61 error,
62 state,
63 partial_stats,
64 writer,
65 }),
66 }
67 }
68 #[inline]
70 #[must_use]
71 pub const fn error(&self) -> &FsError {
72 &self.parts.error
73 }
74 #[inline]
76 #[must_use]
77 pub const fn state(&self) -> CopyFailureState {
78 self.parts.state
79 }
80 #[inline]
82 #[must_use]
83 pub const fn partial_stats(&self) -> &CopyStats {
84 &self.parts.partial_stats
85 }
86 #[inline]
88 #[must_use]
89 pub const fn has_recovery(&self) -> bool {
90 self.parts.writer.is_some()
91 }
92
93 #[inline]
95 #[must_use]
96 pub fn recovery(&self) -> Option<&WriterRecovery> {
97 self.parts.writer.as_ref()
98 }
99
100 #[inline]
102 #[must_use]
103 pub fn recovery_mut(&mut self) -> Option<&mut WriterRecovery> {
104 self.parts.writer.as_mut()
105 }
106
107 #[inline]
110 #[must_use]
111 pub fn take_recovery(&mut self) -> Option<WriterRecovery> {
112 self.parts.writer.take()
113 }
114
115 #[inline]
121 #[must_use]
122 pub fn into_parts(self) -> (FsError, CopyFailureState, CopyStats, Option<WriterRecovery>) {
123 let mut parts = self.parts;
124 (parts.error, parts.state, parts.partial_stats, parts.writer.take())
125 }
126}
127impl Debug for CopyFailure {
128 #[inline]
130 fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
131 formatter
132 .debug_struct("CopyFailure")
133 .field("error", &self.parts.error)
134 .field("state", &self.parts.state)
135 .field("partial_stats", &self.parts.partial_stats)
136 .field("has_recovery", &self.parts.writer.is_some())
137 .finish()
138 }
139}
140
141impl Display for CopyFailure {
142 #[inline]
145 fn fmt(&self, formatter: &mut Formatter<'_>) -> FmtResult {
146 Display::fmt(self.error(), formatter)
147 }
148}
149
150impl Error for CopyFailure {
151 #[inline]
153 fn source(&self) -> Option<&(dyn Error + 'static)> {
154 Some(self.error())
155 }
156}
157
158#[cfg(test)]
159mod tests {
160 use std::hint::black_box;
161
162 use super::CopyFailure;
163 use crate::copy::CopyFailureState;
164 use crate::copy::CopyStats;
165 use crate::error::FsError;
166 use crate::error::FsErrorKind;
167 use crate::error::FsOperation;
168 use crate::write::WriterRecovery;
169
170 #[test]
171 fn recovery_accessors_are_executed_at_runtime() {
172 let has_recovery: fn(&CopyFailure) -> bool = black_box(CopyFailure::has_recovery);
173 let recovery: fn(&CopyFailure) -> Option<&WriterRecovery> = black_box(CopyFailure::recovery);
174 let recovery_mut: for<'a> fn(&'a mut CopyFailure) -> Option<&'a mut WriterRecovery> =
175 black_box(CopyFailure::recovery_mut);
176 let take_recovery: fn(&mut CopyFailure) -> Option<WriterRecovery> = black_box(CopyFailure::take_recovery);
177 let mut failure = CopyFailure::new(
178 FsError::new(FsErrorKind::NotFound, FsOperation::Copy, "missing source"),
179 CopyFailureState::Unchanged,
180 CopyStats::default(),
181 None,
182 );
183
184 assert!(!has_recovery(&failure));
185 assert!(recovery(&failure).is_none());
186 assert!(recovery_mut(&mut failure).is_none());
187 assert!(take_recovery(&mut failure).is_none());
188 }
189}