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 {}