Skip to main content

cordis_core/
error.rs

1/// Library-wide result type.
2pub type Result<T, E = Error> = std::result::Result<T, E>;
3
4#[derive(Debug, thiserror::Error)]
5pub enum Error {
6    #[error("service `{name}` is not registered")]
7    MissingService { name: &'static str },
8
9    #[error("service `{name}` is already registered in this scope")]
10    DuplicateService { name: &'static str },
11
12    #[error("service `{name}` was stored with an incompatible type")]
13    ServiceTypeMismatch { name: &'static str },
14
15    #[error("service `{name}` is owned by another activation")]
16    ServiceOwnership { name: &'static str },
17
18    #[error("scope `{name}` is no longer active")]
19    ScopeInactive { name: String },
20
21    #[error("application is shut down")]
22    ApplicationShutdown,
23
24    #[error("plugin is disposed")]
25    PluginDisposed,
26
27    #[error("plugin failed: {0}")]
28    PluginFailed(String),
29
30    #[error("task failed: {0}")]
31    TaskJoin(#[from] tokio::task::JoinError),
32
33    #[error("task did not stop within {seconds} seconds")]
34    TaskTimeout { seconds: u64 },
35
36    #[error("panic captured: {0}")]
37    Panic(String),
38
39    #[error("dependency cycle: {0}")]
40    DependencyCycle(String),
41
42    #[error("cleanup failed: {0}")]
43    Cleanup(String),
44
45    #[error(transparent)]
46    Other(#[from] Box<dyn std::error::Error + Send + Sync>),
47}
48
49impl Error {
50    pub fn cleanup(error: impl std::fmt::Display) -> Self {
51        Self::Cleanup(error.to_string())
52    }
53
54    pub(crate) fn panic(payload: Box<dyn std::any::Any + Send>) -> Self {
55        let message = payload
56            .downcast_ref::<&str>()
57            .map(|value| (*value).to_owned())
58            .or_else(|| payload.downcast_ref::<String>().cloned())
59            .unwrap_or_else(|| "non-string panic payload".to_owned());
60        Self::Panic(message)
61    }
62}