Skip to main content

nsis_plugin/
error.rs

1//! The failure channel.
2//!
3//! An `Err` returned from a [`nsis_fn!`](crate::nsis_fn) body sets
4//! `exec_flags->exec_error`, which is exactly what `IfErrors` reads in the
5//! calling script. `?` on an empty stack therefore does the NSIS-native thing
6//! with no ceremony.
7
8use core::fmt;
9
10/// Result of a plug-in operation.
11pub type Result<T> = core::result::Result<T, Error>;
12
13/// What can go wrong at the plug-in boundary.
14#[derive(Debug, Clone, Copy, PartialEq, Eq)]
15#[non_exhaustive]
16pub enum Error {
17	/// Popped from an empty stack. Mirrors `popstring` returning 1.
18	EmptyStack,
19	/// The installer passed a null `stacktop`, so there is no stack at all.
20	NoStack,
21	/// The installer passed a null `variables` array.
22	NoVariables,
23	/// The installer passed a null `extra_parameters`, or a null member of it.
24	///
25	/// The name is the C field that was missing.
26	Unavailable(&'static str),
27	/// The value was written, but did not fit in `string_size` characters.
28	///
29	/// The truncated value *is* stored — this mirrors `lstrcpyn` — and the
30	/// error exists so the caller can decide whether that matters.
31	Truncated,
32	/// `GlobalAlloc` returned null.
33	OutOfMemory,
34	/// The installer is older than the plug-in ABI version required.
35	UnsupportedApiVersion {
36		/// What `exec_flags->plugin_api_version` reported.
37		found: i32,
38		/// What was required.
39		required: i32,
40	},
41	/// The plug-in's own error, for `?` in user code that has no better fit.
42	Failed,
43}
44
45impl fmt::Display for Error {
46	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
47		match self {
48			Self::EmptyStack => f.write_str("stack is empty"),
49			Self::NoStack => f.write_str("installer passed a null stack pointer"),
50			Self::NoVariables => f.write_str("installer passed a null variables array"),
51			Self::Unavailable(what) => write!(f, "installer did not provide `{what}`"),
52			Self::Truncated => f.write_str("value did not fit in the installer's string_size"),
53			Self::OutOfMemory => f.write_str("GlobalAlloc failed"),
54			Self::UnsupportedApiVersion { found, required } => write!(
55				f,
56				"installer plug-in API version {found:#010x} is older than the required {required:#010x}"
57			),
58			Self::Failed => f.write_str("plug-in reported failure"),
59		}
60	}
61}
62
63impl core::error::Error for Error {}