async_tempfile/errors.rs
1use std::fmt::{Display, Formatter};
2use std::path::PathBuf;
3
4#[derive(Debug)]
5pub enum Error {
6 /// An invalid or missing directory was specified.
7 InvalidDirectory,
8 /// An invalid or missing file was specified.
9 InvalidFile,
10 /// A name affix (prefix or suffix) contained a path separator.
11 ///
12 /// Affixes are composed into a single path component
13 /// (`{prefix}{random}{suffix}`); a separator would let the name escape the
14 /// target directory, so such affixes are rejected before any filesystem
15 /// access. The target directory itself is unaffected (and still valid).
16 InvalidAffix,
17 /// An I/O error occurred.
18 Io(std::io::Error),
19}
20
21impl Display for Error {
22 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
23 match self {
24 Self::InvalidDirectory => write!(f, "An invalid directory was specified"),
25 Self::InvalidFile => write!(f, "An invalid file name was specified"),
26 Self::InvalidAffix => {
27 write!(f, "A name prefix or suffix contained a path separator")
28 }
29 Self::Io(e) => Display::fmt(e, f),
30 }
31 }
32}
33
34impl std::error::Error for Error {}
35
36impl From<std::io::Error> for Error {
37 fn from(e: std::io::Error) -> Self {
38 Self::Io(e)
39 }
40}
41
42/// The error returned by [`crate::TempFile::persist`] and
43/// [`crate::TempDir::persist`] when the move to the target path fails.
44///
45/// On failure the temporary file or directory is **not** deleted: it is left in
46/// place at [`PersistError::path`] so the caller can recover the data instead of
47/// losing it. To restore automatic cleanup, re-wrap that path with
48/// `from_existing(path, Ownership::Owned)`.
49///
50/// There is intentionally no `From<PersistError> for Error` conversion: a
51/// blanket `?` would silently drop [`PersistError::path`], the one piece of
52/// information that makes recovery possible. Handle the two fields explicitly,
53/// or use `map_err(|e| e.error)` if you only care about the underlying error.
54#[derive(Debug)]
55pub struct PersistError {
56 /// The underlying error that prevented the move (for example a cross-device
57 /// rename, a permission error, or a missing target directory).
58 pub error: Error,
59 /// The path at which the temporary file or directory still resides.
60 pub path: PathBuf,
61}
62
63impl Display for PersistError {
64 fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
65 write!(
66 f,
67 "failed to persist temporary at {:?}: {}",
68 self.path, self.error
69 )
70 }
71}
72
73impl std::error::Error for PersistError {
74 fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
75 Some(&self.error)
76 }
77}