peace_item_file_download/
file_download_error.rs

1use std::path::PathBuf;
2
3#[cfg(feature = "error_reporting")]
4use peace::miette::{self, SourceSpan};
5
6/// Error while managing a file download.
7#[cfg_attr(feature = "error_reporting", derive(peace::miette::Diagnostic))]
8#[derive(Debug, thiserror::Error)]
9pub enum FileDownloadError {
10    #[error("Failed to open destination file.")]
11    DestFileOpen(#[source] std::io::Error),
12    #[error("Failed to read destination file metadata.")]
13    DestMetadataRead(#[source] std::io::Error),
14    #[error("Failed to read destination file contents.")]
15    DestFileRead(#[source] std::io::Error),
16
17    #[error("Failed to create directories: `{}`.", dest_parent.display())]
18    #[cfg_attr(
19        feature = "error_reporting",
20        diagnostic(
21            code(peace_item_file_download::dest_parent_dirs_create),
22            help(
23                "Ensure that `{}` is not a file, or rerun the command with a different path.",
24                dest_parent.display())),
25    )]
26    DestParentDirsCreate {
27        /// Destination file path.
28        dest: PathBuf,
29        /// Destination parent directory path.
30        dest_parent: PathBuf,
31        /// String representation of the destination path.
32        #[cfg(feature = "error_reporting")]
33        #[source_code]
34        dest_display: String,
35        #[cfg(feature = "error_reporting")]
36        #[label]
37        parent_dirs_span: SourceSpan,
38        /// Underlying IO error
39        #[source]
40        error: std::io::Error,
41    },
42    #[error("Failed to open `{}` for writing.", dest.display())]
43    #[cfg_attr(
44        feature = "error_reporting",
45        diagnostic(
46            code(peace_item_file_download::dest_file_create),
47            help(
48                "Ensure that `{}` is not a directory, or rerun the command with a different path.",
49                dest.display())),
50    )]
51    DestFileCreate {
52        /// Approximation of the init command that defined the destination path.
53        #[cfg_attr(feature = "error_reporting", source_code)]
54        init_command_approx: String,
55        /// Span of the destination path within the init command.
56        #[cfg(feature = "error_reporting")]
57        #[label = "defined here"]
58        dest_span: SourceSpan,
59        /// Destination file path.
60        dest: PathBuf,
61        /// Underlying IO error
62        #[source]
63        error: std::io::Error,
64    },
65    #[error("Failed to delete destination file.")]
66    DestFileRemove(#[source] std::io::Error),
67    #[error("Failed to parse source URL.")]
68    SrcUrlParse(url::ParseError),
69    #[cfg_attr(
70        feature = "error_reporting",
71        diagnostic(help(
72            "Check that the URL is reachable:\n\
73            {}\n\
74            Make sure you are connected to the internet and try again.",
75            src
76        ))
77    )]
78    #[error("Failed to download file.")]
79    SrcGet {
80        /// Source URL.
81        src: url::Url,
82        /// Underlying error.
83        #[source]
84        error: reqwest::Error,
85    },
86    #[error("Failed to fetch source file metadata. Response status code: {status_code}")]
87    SrcFileUndetermined { status_code: reqwest::StatusCode },
88    #[error("Failed to read source file content.")]
89    SrcFileRead(#[source] reqwest::Error),
90    #[error("Failed to stream source file content.")]
91    ResponseBytesStream(#[source] reqwest::Error),
92    #[error("Failed to transfer source file content.")]
93    ResponseFileWrite(#[source] std::io::Error),
94
95    // Native errors
96    #[cfg(not(target_arch = "wasm32"))]
97    #[error("Failed to read current executable path.")]
98    CurrentExeRead(#[source] std::io::Error),
99    #[cfg(not(target_arch = "wasm32"))]
100    #[error("Failed to get current executable name from path.")]
101    CurrentExeNameRead,
102    /// This one should be relatively unreachable.
103    #[cfg(not(target_arch = "wasm32"))]
104    #[error("Failed to format string in memory.")]
105    FormatString(#[source] std::fmt::Error),
106
107    // WASM errors.
108    #[cfg(target_arch = "wasm32")]
109    #[error("Failed to read bytes from response.")]
110    ResponseBytesRead(#[source] reqwest::Error),
111    #[cfg(target_arch = "wasm32")]
112    #[error("Failed to read text from response.")]
113    ResponseTextRead(#[source] reqwest::Error),
114
115    // === Framework errors === //
116    /// A `peace` runtime error occurred.
117    #[error("A `peace` runtime error occurred.")]
118    PeaceRtError(
119        #[cfg_attr(feature = "error_reporting", diagnostic_source)]
120        #[source]
121        #[from]
122        peace::rt_model::Error,
123    ),
124}
125
126impl FileDownloadError {
127    /// Returns `FileDownloadError::SrcGet` from a get request error.
128    pub(crate) fn src_get(src: url::Url, error: reqwest::Error) -> Self {
129        FileDownloadError::SrcGet { src, error }
130    }
131}