rust_pty/
lib.rs

1//! rust-pty: Cross-platform async PTY library
2//!
3//! This crate provides a unified async interface for pseudo-terminal (PTY) operations
4//! across Unix (Linux, macOS) and Windows (`ConPTY`) platforms.
5//!
6//! # Platform Support
7//!
8//! - **Unix**: Uses `rustix` for PTY allocation and process management
9//! - **Windows**: Uses `ConPTY` via `windows-sys` (Windows 10 1809+)
10//!
11//! # Quick Start
12//!
13//! ```ignore
14//! use rust_pty::{NativePtySystem, PtySystem, PtyConfig};
15//! use tokio::io::{AsyncReadExt, AsyncWriteExt};
16//!
17//! #[tokio::main]
18//! async fn main() -> Result<(), Box<dyn std::error::Error>> {
19//!     let config = PtyConfig::default();
20//!     let (mut master, mut child) = NativePtySystem::spawn_shell(&config).await?;
21//!
22//!     // Write a command
23//!     master.write_all(b"echo hello\n").await?;
24//!
25//!     // Read output
26//!     let mut buf = [0u8; 1024];
27//!     let n = master.read(&mut buf).await?;
28//!     println!("{}", String::from_utf8_lossy(&buf[..n]));
29//!
30//!     // Clean up
31//!     child.kill()?;
32//!     Ok(())
33//! }
34//! ```
35//!
36//! # Features
37//!
38//! - **Async I/O**: First-class async support with Tokio
39//! - **Cross-platform**: Single API for Unix and Windows
40//! - **Type-safe**: Strong typing with proper error handling
41//! - **Zero-copy**: Efficient buffer management for high-throughput scenarios
42
43pub mod config;
44pub mod error;
45pub mod traits;
46
47#[cfg(unix)]
48pub mod unix;
49
50#[cfg(windows)]
51pub mod windows;
52
53// Re-export primary types
54pub use config::{PtyConfig, PtyConfigBuilder, PtySignal, WindowSize};
55pub use error::{PtyError, Result};
56pub use traits::{ExitStatus, PtyChild, PtyMaster, PtySystem};
57// Platform-specific re-exports
58#[cfg(unix)]
59pub use unix::{NativePtySystem, UnixPtyChild, UnixPtyMaster, UnixPtySystem};
60#[cfg(windows)]
61pub use windows::{NativePtySystem, WindowsPtyChild, WindowsPtyMaster, WindowsPtySystem};
62
63/// Create a PTY with the default configuration and spawn a shell.
64///
65/// This is a convenience function that uses the platform's native PTY system.
66///
67/// # Errors
68///
69/// Returns an error if PTY creation or shell spawning fails.
70#[cfg(unix)]
71pub async fn spawn_shell() -> Result<(UnixPtyMaster, UnixPtyChild)> {
72    UnixPtySystem::spawn_shell(&PtyConfig::default()).await
73}
74
75/// Create a PTY with the default configuration and spawn a shell.
76///
77/// This is a convenience function that uses the platform's native PTY system.
78///
79/// # Errors
80///
81/// Returns an error if PTY creation or shell spawning fails.
82#[cfg(windows)]
83pub async fn spawn_shell() -> Result<(WindowsPtyMaster, WindowsPtyChild)> {
84    WindowsPtySystem::spawn_shell(&PtyConfig::default()).await
85}
86
87#[cfg(test)]
88mod tests {
89    use super::*;
90
91    #[test]
92    fn default_config() {
93        let config = PtyConfig::default();
94        assert_eq!(config.window_size, (80, 24));
95        assert!(config.new_session);
96    }
97
98    #[test]
99    fn window_size_conversion() {
100        let size = WindowSize::new(120, 40);
101        assert_eq!(size.cols, 120);
102        assert_eq!(size.rows, 40);
103    }
104
105    #[cfg(unix)]
106    #[tokio::test]
107    async fn spawn_echo() {
108        let config = PtyConfig::default();
109        let result = UnixPtySystem::spawn("echo", ["test"], &config).await;
110
111        // May fail in some CI environments
112        if let Ok((mut master, mut child)) = result {
113            let _ = child.wait().await;
114            master.close().ok();
115        }
116    }
117}