modio/util/download/
error.rs

1use std::fmt;
2
3use crate::types::id::{FileId, GameId, ModId};
4
5type Source = Box<dyn std::error::Error + Send + Sync>;
6
7/// The Errors that may occur when using [`Download::download`].
8///
9/// [`Download::download`]: crate::util::Download::download
10pub struct Error {
11    kind: ErrorKind,
12    source: Option<Source>,
13}
14
15impl Error {
16    #[inline]
17    pub(crate) fn new(kind: ErrorKind) -> Self {
18        Self { kind, source: None }
19    }
20
21    #[inline]
22    pub(crate) fn with<E: Into<Source>>(mut self, source: E) -> Self {
23        self.source = Some(source.into());
24        self
25    }
26
27    pub const fn kind(&self) -> &ErrorKind {
28        &self.kind
29    }
30}
31
32impl Error {
33    #[inline]
34    pub(crate) fn request<E: Into<Source>>(source: E) -> Self {
35        Self::new(ErrorKind::Request).with(source)
36    }
37
38    #[inline]
39    pub(crate) fn body<E: Into<Source>>(source: E) -> Self {
40        Self::new(ErrorKind::Body).with(source)
41    }
42}
43
44impl fmt::Debug for Error {
45    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
46        let mut s = f.debug_struct("Error");
47
48        s.field("kind", &self.kind);
49        if let Some(ref source) = self.source {
50            s.field("source", source);
51        }
52        s.finish()
53    }
54}
55
56impl fmt::Display for Error {
57    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
58        match &self.kind {
59            ErrorKind::Request => fmt.write_str("request failed"),
60            ErrorKind::Body => fmt.write_str("failed to load response body"),
61            ErrorKind::Io => fmt.write_str("IO error"),
62            ErrorKind::ModNotFound { game_id, mod_id } => write!(
63                fmt,
64                "Mod {{id: {mod_id}, game_id: {game_id}}} not found.",
65            ),
66            ErrorKind::FileNotFound {
67                game_id,
68                mod_id,
69                file_id,
70            } => write!(
71                fmt,
72                "Mod {{id: {mod_id}, game_id: {game_id}}}: File {{ id: {file_id} }} not found.",
73            ),
74            ErrorKind::MultipleFilesFound {
75                game_id,
76                mod_id,
77                version,
78            } => write!(
79                fmt,
80                "Mod {{id: {mod_id}, game_id: {game_id}}}: Multiple files found for version '{version}'.",
81            ),
82            ErrorKind::NoPrimaryFile { game_id, mod_id } => write!(
83                fmt,
84                "Mod {{id: {mod_id}, game_id: {game_id}}} Mod has no primary file.",
85            ),
86            ErrorKind::VersionNotFound {
87                game_id,
88                mod_id,
89                version,
90            } => write!(
91                fmt,
92                "Mod {{id: {mod_id}, game_id: {game_id}}}: No file with version '{version}' found.",
93            ),
94        }
95    }
96}
97
98impl std::error::Error for Error {
99    fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
100        self.source.as_ref().map(|e| &**e as _)
101    }
102}
103
104#[derive(Debug)]
105pub enum ErrorKind {
106    Request,
107    Body,
108    Io,
109    /// The mod has not found.
110    ModNotFound {
111        game_id: GameId,
112        mod_id: ModId,
113    },
114    /// The mod has no primary file.
115    NoPrimaryFile {
116        game_id: GameId,
117        mod_id: ModId,
118    },
119    /// The specific file of a mod was not found.
120    FileNotFound {
121        game_id: GameId,
122        mod_id: ModId,
123        file_id: FileId,
124    },
125    /// Multiple files for a given version were found and the policy was set to
126    /// [`ResolvePolicy::Fail`].
127    ///
128    /// [`ResolvePolicy::Fail`]: super::ResolvePolicy::Fail
129    MultipleFilesFound {
130        game_id: GameId,
131        mod_id: ModId,
132        version: String,
133    },
134    /// No file for a given version was found.
135    VersionNotFound {
136        game_id: GameId,
137        mod_id: ModId,
138        version: String,
139    },
140}