mod async_adapter;
mod child;
mod conpty;
mod pipes;
use std::ffi::OsStr;
use std::future::Future;
use std::sync::Arc;
pub use async_adapter::WindowsPtyMaster;
pub use child::{WindowsPtyChild, spawn_child};
pub use conpty::{ConPty, is_conpty_available};
pub use pipes::{PipePair, create_input_pipe, create_output_pipe, set_inheritable};
use crate::config::{PtyConfig, WindowSize};
use crate::error::{PtyError, Result};
use crate::traits::PtySystem;
#[derive(Debug, Clone, Copy, Default)]
pub struct WindowsPtySystem;
impl PtySystem for WindowsPtySystem {
type Master = WindowsPtyMaster;
type Child = WindowsPtyChild;
fn spawn<S, I>(
program: S,
args: I,
config: &PtyConfig,
) -> impl Future<Output = Result<(Self::Master, Self::Child)>> + Send
where
S: AsRef<OsStr> + Send,
I: IntoIterator + Send,
I::Item: AsRef<OsStr>,
{
async move {
if !is_conpty_available() {
return Err(PtyError::ConPtyNotAvailable);
}
let input_pipe = create_input_pipe()?;
let output_pipe = create_output_pipe()?;
let window_size = WindowSize::from(config.window_size);
let mut conpty = ConPty::new(
window_size,
input_pipe.read,
output_pipe.write,
input_pipe.write,
output_pipe.read,
)?;
let child = spawn_child(conpty.handle(), program, args, config)?;
conpty.close_pty_pipes();
let input_handle = conpty.input().try_clone().map_err(|e| PtyError::Spawn(e))?;
let output_handle = conpty
.output()
.try_clone()
.map_err(|e| PtyError::Spawn(e))?;
let conpty = Arc::new(conpty);
let conpty_for_resize = Arc::clone(&conpty);
let master = WindowsPtyMaster::new(
input_handle,
output_handle,
move |size| conpty_for_resize.resize(size),
window_size,
);
Ok((master, child))
}
}
}
pub type NativePtySystem = WindowsPtySystem;
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn check_availability() {
let _ = is_conpty_available();
}
}