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}