1#[cfg(windows)]
3use std::char;
4use std::error::Error;
5use std::fmt;
6use std::io;
7
8#[expect(clippy::module_name_repetitions)]
12#[derive(Debug)]
13#[non_exhaustive]
14pub enum ReadlineError {
15 Io(io::Error),
17 Eof,
19 Interrupted,
21 #[cfg(unix)]
23 Errno(nix::Error),
24 WindowResized,
26 #[cfg(windows)]
28 Decode(char::DecodeUtf16Error),
29 #[cfg(windows)]
31 SystemError(clipboard_win::ErrorCode),
32 #[cfg(feature = "with-sqlite-history")]
34 SQLiteError(rusqlite::Error),
35}
36
37impl fmt::Display for ReadlineError {
38 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
39 match *self {
40 Self::Io(ref err) => err.fmt(f),
41 Self::Eof => write!(f, "EOF"),
42 Self::Interrupted => write!(f, "Interrupted"),
43 #[cfg(unix)]
44 Self::Errno(ref err) => err.fmt(f),
45 Self::WindowResized => write!(f, "WindowResized"),
46 #[cfg(windows)]
47 Self::Decode(ref err) => err.fmt(f),
48 #[cfg(windows)]
49 Self::SystemError(ref err) => err.fmt(f),
50 #[cfg(feature = "with-sqlite-history")]
51 Self::SQLiteError(ref err) => err.fmt(f),
52 }
53 }
54}
55
56impl Error for ReadlineError {
57 fn source(&self) -> Option<&(dyn Error + 'static)> {
58 match *self {
59 Self::Io(ref err) => Some(err),
60 Self::Eof => None,
61 Self::Interrupted => None,
62 #[cfg(unix)]
63 Self::Errno(ref err) => Some(err),
64 Self::WindowResized => None,
65 #[cfg(windows)]
66 Self::Decode(ref err) => Some(err),
67 #[cfg(windows)]
68 Self::SystemError(_) => None,
69 #[cfg(feature = "with-sqlite-history")]
70 Self::SQLiteError(ref err) => Some(err),
71 }
72 }
73}
74
75#[cfg(unix)]
76#[derive(Debug)]
77pub(crate) struct WindowResizedError;
78#[cfg(unix)]
79impl fmt::Display for WindowResizedError {
80 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
81 write!(f, "WindowResized")
82 }
83}
84#[cfg(unix)]
85impl Error for WindowResizedError {}
86
87impl From<io::Error> for ReadlineError {
88 fn from(err: io::Error) -> Self {
89 #[cfg(unix)]
90 if err.kind() == io::ErrorKind::Interrupted {
91 if let Some(e) = err.get_ref() {
92 if e.downcast_ref::<WindowResizedError>().is_some() {
93 return Self::WindowResized;
94 }
95 }
96 }
97 Self::Io(err)
98 }
99}
100
101impl From<io::ErrorKind> for ReadlineError {
102 fn from(kind: io::ErrorKind) -> Self {
103 Self::Io(io::Error::from(kind))
104 }
105}
106
107#[cfg(unix)]
108impl From<nix::Error> for ReadlineError {
109 fn from(err: nix::Error) -> Self {
110 Self::Errno(err)
111 }
112}
113
114#[cfg(windows)]
115impl From<char::DecodeUtf16Error> for ReadlineError {
116 fn from(err: char::DecodeUtf16Error) -> Self {
117 Self::Io(io::Error::new(io::ErrorKind::InvalidData, err))
118 }
119}
120
121#[cfg(windows)]
122impl From<std::string::FromUtf8Error> for ReadlineError {
123 fn from(err: std::string::FromUtf8Error) -> Self {
124 Self::Io(io::Error::new(io::ErrorKind::InvalidData, err))
125 }
126}
127
128#[cfg(unix)]
129impl From<fmt::Error> for ReadlineError {
130 fn from(err: fmt::Error) -> Self {
131 Self::Io(io::Error::new(io::ErrorKind::Other, err))
132 }
133}
134
135#[cfg(windows)]
136impl From<clipboard_win::ErrorCode> for ReadlineError {
137 fn from(err: clipboard_win::ErrorCode) -> Self {
138 Self::SystemError(err)
139 }
140}
141
142#[cfg(feature = "with-sqlite-history")]
143impl From<rusqlite::Error> for ReadlineError {
144 fn from(err: rusqlite::Error) -> Self {
145 Self::SQLiteError(err)
146 }
147}