1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
/*!
# Argyle: Errors

This is the obligatory error enum. It implements `Copy` unless the crate
feature `dynamic-help` is enabled, in which case it can only be `Clone`.
*/

use std::{
	error::Error,
	fmt,
};



#[derive(Debug, Clone, Eq, PartialEq)]
#[cfg_attr(not(feature = "dynamic-help"), derive(Copy))]
/// # Error Struct.
pub enum ArgyleError {
	/// A custom error.
	Custom(&'static str),
	/// Missing anything/everything.
	Empty,
	/// No trailing args.
	NoArg,
	/// Expected subcommand.
	NoSubCmd,
	/// Miscellaneous Silent Failure.
	///
	/// This has no corresponding error text, but does have its own exit code.
	Passthru(i32),
	/// Too many arguments.
	TooManyArgs,
	/// Too many options defined.
	TooManyKeys,

	#[cfg(feature = "dynamic-help")]
	/// Wants subcommand help.
	WantsDynamicHelp(Option<Box<[u8]>>),

	/// Wants help.
	WantsHelp,
	/// Wants version.
	WantsVersion,
}

impl AsRef<str> for ArgyleError {
	#[inline]
	fn as_ref(&self) -> &str { self.as_str() }
}

impl Error for ArgyleError {}

impl fmt::Display for ArgyleError {
	#[inline]
	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
		f.write_str(self.as_str())
	}
}

impl ArgyleError {
	#[must_use]
	/// # Exit code.
	///
	/// This returns the exit code for the error. Non-error errors like help
	/// and version have a non-error exit code of `0`. [`ArgyleError::Passthru`]
	/// returns whatever code was defined, while everything else just returns
	/// `1`.
	pub const fn exit_code(&self) -> i32 {
		match self {
			Self::Passthru(c) => *c,

			#[cfg(feature = "dynamic-help")]
			Self::WantsDynamicHelp(_)
				| Self::WantsHelp
				| Self::WantsVersion => 0,

			#[cfg(not(feature = "dynamic-help"))]
			Self::WantsHelp | Self::WantsVersion => 0,

			_ => 1,
		}
	}

	#[must_use]
	/// # As Str.
	///
	/// Return as a string slice.
	pub const fn as_str(&self) -> &'static str {
		match self {
			Self::Custom(s) => s,
			Self::Empty => "Missing options, flags, arguments, and/or ketchup.",
			Self::NoArg => "Missing required trailing argument.",
			Self::NoSubCmd => "Missing/invalid subcommand.",

			#[cfg(feature = "dynamic-help")]
			Self::Passthru(_)
				| Self::WantsDynamicHelp(_)
				| Self::WantsHelp
				| Self::WantsVersion => "",

			#[cfg(not(feature = "dynamic-help"))]
			Self::Passthru(_)
				| Self::WantsHelp
				| Self::WantsVersion => "",

			Self::TooManyArgs => "Too many arguments.",
			Self::TooManyKeys => "Too many keys.",
		}
	}
}