Skip to main content

rust_expect/
backend.rs

1//! Backend module for different transport implementations.
2//!
3//! This module provides various backends for session communication,
4//! including PTY for local processes and SSH for remote connections.
5
6mod pty;
7
8// Export AsyncPty and PtyHandle for Unix platforms
9#[cfg(unix)]
10pub use pty::{AsyncPty, PtyHandle};
11pub use pty::{EnvMode, PtyConfig, PtySpawner, PtyTransport};
12// Export WindowsAsyncPty and WindowsPtyHandle for Windows platforms
13#[cfg(windows)]
14pub use pty::{WindowsAsyncPty, WindowsPtyHandle};
15
16// SSH backend is conditionally compiled
17#[cfg(feature = "ssh")]
18pub mod ssh;
19
20/// Reaping/liveness probe for a transport that wraps a child process.
21///
22/// `Session::wait`/`wait_timeout` use this to report the child's *real* exit
23/// status after EOF, rather than [`ProcessExitStatus::Unknown`]. Transports
24/// that are not backed by a local child process (SSH channels, mock streams)
25/// rely on the default implementation, which reports `None` (status unknowable)
26/// and so leaves the session reporting `Unknown` — exactly the prior behavior.
27///
28/// [`ProcessExitStatus::Unknown`]: crate::types::ProcessExitStatus::Unknown
29pub trait ChildExit {
30    /// Non-blocking reap.
31    ///
32    /// Returns `Some(status)` once the child has exited and been reaped (the
33    /// status is cached, so repeated calls keep returning it), or `None` while
34    /// the child is still running or its status cannot be determined.
35    fn try_exit_status(&mut self) -> Option<crate::types::ProcessExitStatus> {
36        None
37    }
38}
39
40/// Trait for session backends.
41pub trait Backend {
42    /// The transport type produced by this backend.
43    type Transport;
44
45    /// Check if the backend is available.
46    fn is_available(&self) -> bool;
47
48    /// Get the backend name.
49    fn name(&self) -> &'static str;
50}
51
52/// Available backend types.
53#[derive(Debug, Clone, Copy, PartialEq, Eq)]
54pub enum BackendType {
55    /// Local PTY backend.
56    Pty,
57    /// SSH backend for remote connections.
58    Ssh,
59    /// Mock backend for testing.
60    Mock,
61}
62
63impl BackendType {
64    /// Check if this backend is available.
65    #[must_use]
66    pub const fn is_available(self) -> bool {
67        match self {
68            Self::Pty => cfg!(unix) || cfg!(windows),
69            Self::Ssh => cfg!(feature = "ssh"),
70            Self::Mock => cfg!(feature = "mock"),
71        }
72    }
73
74    /// Get the backend name.
75    #[must_use]
76    pub const fn name(self) -> &'static str {
77        match self {
78            Self::Pty => "pty",
79            Self::Ssh => "ssh",
80            Self::Mock => "mock",
81        }
82    }
83}