inquire/
error.rs

1//! Definitions of `inquire`'s error handling
2
3use core::fmt;
4use std::{error::Error, io};
5
6/// Type alias to define errors that might be thrown by the library user
7/// on callbacks such as validators.
8pub type CustomUserError = Box<dyn Error + Send + Sync + 'static>;
9
10/// Possible errors returned by `inquire` prompts.
11#[derive(Debug)]
12pub enum InquireError {
13    /// The input device is not a TTY, which means that enabling raw mode
14    /// on the terminal in order to listen to input events is not possible.
15    NotTTY,
16
17    /// The given prompt configuration is not valid. A detailed error message
18    /// is contained in the value string.
19    InvalidConfiguration(String),
20
21    /// Error while executing IO operations.
22    IO(io::Error),
23
24    /// The user canceled the operation by pressing ESC.
25    OperationCanceled,
26
27    /// The operation was interrupted by the user after they
28    /// pressed Ctrl+C.
29    ///
30    /// This error will be returned only when using `crossterm`
31    /// or `termion` as the terminal back-end. If using `console`,
32    /// pressing Ctrl+C will trigger SIGINT.
33    OperationInterrupted,
34
35    /// Error while executing IO operations.
36    Custom(CustomUserError),
37}
38
39impl Error for InquireError {
40    fn source(&self) -> Option<&(dyn Error + 'static)> {
41        match self {
42            InquireError::IO(err) => Some(err),
43            InquireError::Custom(err) => Some(err.as_dyn_error()),
44            _ => None,
45        }
46    }
47}
48
49trait AsDynError<'a> {
50    fn as_dyn_error(&self) -> &(dyn Error + 'a);
51}
52
53impl<'a> AsDynError<'a> for dyn Error + Send + Sync + 'a {
54    #[inline]
55    fn as_dyn_error(&self) -> &(dyn Error + 'a) {
56        self
57    }
58}
59
60impl From<CustomUserError> for InquireError {
61    fn from(err: CustomUserError) -> Self {
62        InquireError::Custom(err)
63    }
64}
65
66impl From<io::Error> for InquireError {
67    fn from(err: io::Error) -> Self {
68        match err.raw_os_error() {
69            Some(25 | 6) => InquireError::NotTTY,
70            _ => InquireError::IO(err),
71        }
72    }
73}
74
75impl fmt::Display for InquireError {
76    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
77        match self {
78            InquireError::NotTTY => f.write_str("The input device is not a TTY"),
79            InquireError::InvalidConfiguration(s) => {
80                write!(f, "The prompt configuration is invalid: {}", s)
81            }
82            InquireError::IO(err) => write!(f, "IO error: {}", err),
83            InquireError::OperationCanceled => f.write_str("Operation was canceled by the user"),
84            InquireError::OperationInterrupted => {
85                f.write_str("Operation was interrupted by the user")
86            }
87            InquireError::Custom(err) => write!(f, "User-provided error: {}", err),
88        }
89    }
90}
91
92/// Result type where errors are of type [InquireError](crate::error::InquireError)
93pub type InquireResult<T> = Result<T, InquireError>;