rust_pty/
error.rs

1//! Error types for the rust-pty crate.
2//!
3//! This module provides a unified error type [`PtyError`] that covers all
4//! possible failure modes when working with pseudo-terminals.
5
6use std::io;
7
8/// The error type for PTY operations.
9///
10/// This enum represents all possible errors that can occur when creating,
11/// using, or managing pseudo-terminals across different platforms.
12#[derive(Debug, thiserror::Error)]
13pub enum PtyError {
14    /// Failed to create a new PTY.
15    #[error("failed to create PTY: {0}")]
16    Create(#[source] io::Error),
17
18    /// Failed to spawn a child process.
19    #[error("failed to spawn process: {0}")]
20    Spawn(#[source] io::Error),
21
22    /// An I/O error occurred during PTY operations.
23    #[error("PTY I/O error: {0}")]
24    Io(#[from] io::Error),
25
26    /// Failed to set terminal attributes.
27    #[error("failed to set terminal attributes: {0}")]
28    SetAttributes(#[source] io::Error),
29
30    /// Failed to get terminal attributes.
31    #[error("failed to get terminal attributes: {0}")]
32    GetAttributes(#[source] io::Error),
33
34    /// Failed to resize the PTY.
35    #[error("failed to resize PTY: {0}")]
36    Resize(#[source] io::Error),
37
38    /// The PTY has been closed.
39    #[error("PTY has been closed")]
40    Closed,
41
42    /// The child process has exited.
43    #[error("child process exited with status: {0}")]
44    ProcessExited(i32),
45
46    /// The child process was killed by a signal.
47    #[cfg(unix)]
48    #[error("child process killed by signal: {0}")]
49    ProcessSignaled(i32),
50
51    /// Failed to send a signal to the child process.
52    #[error("failed to send signal: {0}")]
53    Signal(#[source] io::Error),
54
55    /// Failed to wait for the child process.
56    #[error("failed to wait for child: {0}")]
57    Wait(#[source] io::Error),
58
59    /// Invalid window size specified.
60    #[error("invalid window size: {width}x{height}")]
61    InvalidWindowSize {
62        /// The requested width.
63        width: u16,
64        /// The requested height.
65        height: u16,
66    },
67
68    /// The operation timed out.
69    #[error("operation timed out")]
70    Timeout,
71
72    /// Platform-specific error on Unix.
73    #[cfg(unix)]
74    #[error("Unix error: {message}")]
75    Unix {
76        /// Description of the error.
77        message: String,
78        /// The underlying errno value.
79        errno: i32,
80    },
81
82    /// Platform-specific error on Windows.
83    #[cfg(windows)]
84    #[error("Windows error: {message} (code: {code})")]
85    Windows {
86        /// Description of the error.
87        message: String,
88        /// The Windows error code.
89        code: u32,
90    },
91
92    /// ConPTY is not available (Windows version too old).
93    #[cfg(windows)]
94    #[error("ConPTY is not available on this Windows version")]
95    ConPtyNotAvailable,
96}
97
98/// A specialized Result type for PTY operations.
99pub type Result<T> = std::result::Result<T, PtyError>;
100
101#[cfg(unix)]
102impl From<rustix::io::Errno> for PtyError {
103    fn from(errno: rustix::io::Errno) -> Self {
104        Self::Io(io::Error::from_raw_os_error(errno.raw_os_error()))
105    }
106}
107
108#[cfg(test)]
109mod tests {
110    use super::*;
111
112    #[test]
113    fn error_display() {
114        let err = PtyError::Closed;
115        assert_eq!(err.to_string(), "PTY has been closed");
116    }
117
118    #[test]
119    fn error_from_io() {
120        let io_err = io::Error::new(io::ErrorKind::NotFound, "not found");
121        let pty_err: PtyError = io_err.into();
122        assert!(matches!(pty_err, PtyError::Io(_)));
123    }
124}