restart_manager/error.rs
1//! Stable error classification without exposing implementation details.
2
3/// Specialised result alias used by this crate.
4pub type Result<T> = std::result::Result<T, Error>;
5
6/// A stable, non-exhaustive classification of failures.
7#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
8#[non_exhaustive]
9pub enum ErrorKind {
10 /// The requested operating-system operation is unavailable on this target.
11 UnsupportedPlatform,
12 /// All 64 Restart Manager session slots in the user session are occupied.
13 SessionLimit,
14 /// A session key was malformed, expired, or otherwise rejected.
15 InvalidSessionKey,
16 /// A shutdown or restart operation was cancelled.
17 Cancelled,
18 /// Windows denied access to a resource or process.
19 AccessDenied,
20 /// Input could not be represented by the native API.
21 InvalidInput,
22 /// Restart Manager does not accept directories as file resources.
23 DirectoryNotSupported,
24 /// A collection was too large for the native `u32` count fields.
25 TooManyResources,
26 /// Another process-wide progress callback operation is active.
27 CallbackInUse,
28 /// The affected-application or filter list changed through every retry.
29 DataChanged,
30 /// Windows returned an internally inconsistent buffer.
31 MalformedOsData,
32 /// Windows requires a system reboot before this operation can proceed.
33 RebootRequired,
34 /// At least one affected application could not be shut down.
35 ShutdownIncomplete,
36 /// At least one stopped application could not be restarted.
37 RestartIncomplete,
38 /// An operation was requested in an invalid native sequence.
39 OperationOutOfSequence,
40 /// Restart Manager could not access its registry state.
41 RegistryUnavailable,
42 /// The selected filter does not exist.
43 FilterNotFound,
44 /// The operating system could not allocate required memory.
45 OutOfMemory,
46 /// This process already owns a crate-managed restart registration.
47 ApplicationRestartInUse,
48 /// A dedicated asynchronous worker thread could not be created or failed.
49 AsyncWorkerUnavailable,
50 /// The weak cancellation capability refers to an ended session.
51 SessionEnded,
52 /// Another Windows error not covered by a more specific classification.
53 Os,
54}
55
56/// An error returned by the safe Restart Manager API.
57///
58/// Its representation is private. Match on [`Error::kind`] and use
59/// [`Error::raw_os_error`] when the precise Win32 value matters.
60#[derive(Debug, Clone, PartialEq, Eq, thiserror::Error)]
61#[error("{message}")]
62pub struct Error {
63 kind: ErrorKind,
64 raw_os_error: Option<u32>,
65 raw_hresult: Option<i32>,
66 message: String,
67}
68
69impl Error {
70 /// Returns the stable classification for this error.
71 #[must_use]
72 pub const fn kind(&self) -> ErrorKind {
73 self.kind
74 }
75
76 /// Returns the original Win32 error code, when the failure came from Windows.
77 #[must_use]
78 pub const fn raw_os_error(&self) -> Option<u32> {
79 self.raw_os_error
80 }
81
82 /// Returns the original HRESULT for application-restart failures.
83 #[must_use]
84 pub const fn raw_hresult(&self) -> Option<i32> {
85 self.raw_hresult
86 }
87
88 pub(crate) fn new(
89 kind: ErrorKind,
90 raw_os_error: Option<u32>,
91 message: impl Into<String>,
92 ) -> Self {
93 Self {
94 kind,
95 raw_os_error,
96 raw_hresult: None,
97 message: message.into(),
98 }
99 }
100
101 pub(crate) fn from_hresult(kind: ErrorKind, hresult: i32, message: impl Into<String>) -> Self {
102 Self {
103 kind,
104 raw_os_error: None,
105 raw_hresult: Some(hresult),
106 message: message.into(),
107 }
108 }
109}
110
111/// Error returned when parsing a Restart Manager session key.
112#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, thiserror::Error)]
113#[error("a session key must contain exactly 32 ASCII hexadecimal characters")]
114pub struct ParseSessionKeyError;