Skip to main content

shell_tunnel/pty/
mod.rs

1//! PTY (Pseudo-Terminal) abstraction layer.
2//!
3//! This module provides a platform-independent interface for working with
4//! pseudo-terminals. It supports both Unix PTY and Windows ConPTY.
5
6mod async_adapter;
7mod native;
8
9pub use async_adapter::{AsyncPtyReader, AsyncPtyWriter};
10pub use native::{default_shell, NativePty, SpawnedShell};
11
12use std::io::{Read, Write};
13
14/// Size of a PTY in characters.
15#[derive(Debug, Clone, Copy, PartialEq, Eq)]
16pub struct PtySize {
17    /// Number of rows (height).
18    pub rows: u16,
19    /// Number of columns (width).
20    pub cols: u16,
21}
22
23impl PtySize {
24    /// Create a new PtySize with the given dimensions.
25    pub fn new(rows: u16, cols: u16) -> Self {
26        Self { rows, cols }
27    }
28}
29
30impl Default for PtySize {
31    fn default() -> Self {
32        Self { rows: 24, cols: 80 }
33    }
34}
35
36/// A handle to a spawned PTY process.
37pub struct PtyHandle<R: Read + Send, W: Write + Send> {
38    /// Reader for the PTY output.
39    pub reader: R,
40    /// Writer for the PTY input.
41    pub writer: W,
42    /// Process ID of the spawned child.
43    pub pid: u32,
44    /// The underlying PTY pair (kept alive to prevent cleanup).
45    _pty: Box<dyn std::any::Any + Send>,
46}
47
48impl<R: Read + Send, W: Write + Send> PtyHandle<R, W> {
49    /// Create a new PtyHandle.
50    pub fn new(reader: R, writer: W, pid: u32, pty: Box<dyn std::any::Any + Send>) -> Self {
51        Self {
52            reader,
53            writer,
54            pid,
55            _pty: pty,
56        }
57    }
58}
59
60#[cfg(test)]
61mod tests {
62    use super::*;
63
64    #[test]
65    fn test_pty_size_default() {
66        let size = PtySize::default();
67        assert_eq!(size.rows, 24);
68        assert_eq!(size.cols, 80);
69    }
70
71    #[test]
72    fn test_pty_size_new() {
73        let size = PtySize::new(40, 120);
74        assert_eq!(size.rows, 40);
75        assert_eq!(size.cols, 120);
76    }
77
78    #[test]
79    fn test_pty_size_equality() {
80        let size1 = PtySize::new(24, 80);
81        let size2 = PtySize::default();
82        assert_eq!(size1, size2);
83
84        let size3 = PtySize::new(30, 100);
85        assert_ne!(size1, size3);
86    }
87}