summaryrefslogtreecommitdiff
path: root/benoit-cli/src/error/mod.rs
blob: 32a9f404a4234812be0c2392d9157642af35612d (plain) (blame)
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
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/*
	Copyright 2021, 2023-2024 Gabriel Bjørnager Jen-
	sen.

	This file is part of benoit.

	benoit is free software: you can redistribute it
	and/or modify it under the terms of the GNU Af-
	fero General Public License as published by the
	Free Software Foundation, either version 3 of
	the License, or (at your option) any later ver-
	sion.

	benoit is distributed in the hope that it will
	be useful, but WITHOUT ANY WARRANTY; without
	even the implied warranty of MERCHANTABILITY or
	FITNESS FOR A PARTICULAR PURPOSE. See the GNU
	Affero General Public License for more details.

	You should have received a copy of the GNU Af-
	fero General Public License along with benoit.
	If not, see <https://www.gnu.org/licenses/>.
*/

use benoit::error::Error as LibError;
use std::error::Error as StdError;
use std::fmt::{Display, Formatter, Result as FmtResult};
use std::io::Error as IoError;
use std::path::PathBuf;
use toml::de::Error as TomlError;

/// Denotes an error.
#[derive(Debug)]
pub enum Error {
	BenoitError { source: LibError },

	ConfigParseFailure { path: PathBuf, source: TomlError },

	ConfigReadFailure { path: PathBuf, source: IoError },

	InvalidConfig { message: String },

	InvalidKeyframe { message: String },

	InvalidPath { path: String, source: IoError },

	FieldLowerBounds { name: String, value: String, limit: String },

	FieldUpperBounds { name: String, value: String, limit: String },

	InfiniteField { name: String },

	MissingConfigField { name: String },

	MissingConfigPath,

	NegativeField { name: String },

	NonNumberField { name: String },

	TooManyCliArguments,

	WrongFieldType { name: String, ok_type: &'static str },
}

impl Display for Error {
	fn fmt(&self, f: &mut Formatter) -> FmtResult {
		#[allow(clippy::enum_glob_use)]
		use Error::*;

		match *self {
			BenoitError { ref source } => {
				write!(f, "{source}")
			},

			ConfigParseFailure { ref path, ref source } => {
				write!(f, "unable to parse configuration at \"{}\": \"{source}\"", path.display())
			}

			ConfigReadFailure { ref path, ref source } => {
				write!(f, "unable to read configuration at \"{}\": \"{source}\"", path.display())
			},

			FieldLowerBounds { ref name, ref value, ref limit } => {
				write!(f, "field `{name}` cannot be less than ({limit}) but was ({value})")
			},

			FieldUpperBounds { ref name, ref value, ref limit } => {
				write!(f, "field `{name}` cannot be greater than ({limit}) but was ({value})")
			},

			InfiniteField { ref name } => {
				write!(f, "field `{name}` must be finite (was infinite)")
			},

			InvalidConfig { ref message } => {
				write!(f, "invalid configuration: {message}")
			},

			InvalidKeyframe { ref message } => {
				write!(f, "invalid keyframe: {message}")
			},

			InvalidPath { ref path, ref source } => {
				write!(f, "invalid path \"{path}\": \"{source}\"")
			},

			MissingConfigField { ref name } => {
				write!(f, "missing configuration field `{name}`")
			},

			MissingConfigPath => {
				write!(f, "missing configuration path")
			},

			NegativeField { ref name } => {
				write!(f, "field `{name}` cannot be negative")
			},

			NonNumberField { ref name } => {
				write!(f, "field `{name}` must be a number (was NaN)")
			},

			TooManyCliArguments => {
				write!(f, "too many arguments provided on the command line")
			},

			WrongFieldType { ref name, ok_type } => {
				write!(f, "type of field `{name} should'be been `{ok_type}`")
			},
		}
	}
}

impl From<LibError> for Error {
	fn from(value: LibError) -> Self {
		Self::BenoitError { source: value }
	}
}

impl StdError for Error {
	fn source(&self) -> Option<&(dyn StdError + 'static)> {
		#[allow(clippy::enum_glob_use)]
		use Error::*;

		#[allow(clippy::match_same_arms, clippy::wildcard_enum_match_arm)]
		match *self {
			BenoitError { ref source } => Some(source),

			ConfigParseFailure { ref source, .. } => Some(source),

			ConfigReadFailure { ref source, .. } => Some(source),

			InvalidPath { ref source, .. } => Some(source),

			_ => None,
		}
	}
}