async_ssh2_lite/session_stream/
mod.rs

1use core::{
2    task::{Context, Poll},
3    time::Duration,
4};
5use std::io::Error as IoError;
6
7use async_trait::async_trait;
8use ssh2::{BlockDirections, Error as Ssh2Error, Session};
9
10use crate::error::Error;
11
12//
13#[cfg(feature = "async-io")]
14mod impl_async_io;
15#[cfg(feature = "tokio")]
16mod impl_tokio;
17
18//
19#[async_trait]
20pub trait AsyncSessionStream {
21    //
22    async fn x_with<R>(
23        &self,
24        op: impl FnMut() -> Result<R, Ssh2Error> + Send,
25        sess: &Session,
26        expected_block_directions: BlockDirections,
27        sleep_dur: Option<Duration>,
28    ) -> Result<R, Error>;
29
30    async fn rw_with<R>(
31        &self,
32        op: impl FnMut() -> Result<R, Ssh2Error> + Send,
33        sess: &Session,
34    ) -> Result<R, Error> {
35        self.x_with(
36            op,
37            sess,
38            BlockDirections::Both,
39            Some(Duration::from_millis(1)),
40        )
41        .await
42    }
43
44    async fn none_with<R>(
45        &self,
46        op: impl FnMut() -> Result<R, Ssh2Error> + Send,
47        sess: &Session,
48    ) -> Result<R, Error> {
49        self.x_with(
50            op,
51            sess,
52            BlockDirections::None,
53            Some(Duration::from_millis(1)),
54        )
55        .await
56    }
57
58    async fn read_with<R>(
59        &self,
60        op: impl FnMut() -> Result<R, Ssh2Error> + Send,
61        sess: &Session,
62    ) -> Result<R, Error> {
63        self.x_with(
64            op,
65            sess,
66            BlockDirections::Inbound,
67            Some(Duration::from_millis(1)),
68        )
69        .await
70    }
71
72    async fn write_with<R>(
73        &self,
74        op: impl FnMut() -> Result<R, Ssh2Error> + Send,
75        sess: &Session,
76    ) -> Result<R, Error> {
77        self.x_with(
78            op,
79            sess,
80            BlockDirections::Outbound,
81            Some(Duration::from_millis(1)),
82        )
83        .await
84    }
85
86    //
87    fn poll_x_with<R>(
88        &self,
89        cx: &mut Context,
90        op: impl FnMut() -> Result<R, IoError> + Send,
91        sess: &Session,
92        expected_block_directions: BlockDirections,
93        sleep_dur: Option<Duration>,
94    ) -> Poll<Result<R, IoError>>;
95
96    fn poll_read_with<R>(
97        &self,
98        cx: &mut Context,
99        op: impl FnMut() -> Result<R, IoError> + Send,
100        sess: &Session,
101    ) -> Poll<Result<R, IoError>> {
102        self.poll_x_with(
103            cx,
104            op,
105            sess,
106            BlockDirections::Inbound,
107            Some(Duration::from_millis(1)),
108        )
109    }
110
111    fn poll_write_with<R>(
112        &self,
113        cx: &mut Context,
114        op: impl FnMut() -> Result<R, IoError> + Send,
115        sess: &Session,
116    ) -> Poll<Result<R, IoError>> {
117        self.poll_x_with(
118            cx,
119            op,
120            sess,
121            BlockDirections::Both,
122            Some(Duration::from_millis(1)),
123        )
124    }
125}
126
127//
128pub trait BlockDirectionsExt {
129    fn is_readable(&self) -> bool;
130    fn is_writable(&self) -> bool;
131}
132impl BlockDirectionsExt for BlockDirections {
133    fn is_readable(&self) -> bool {
134        matches!(self, BlockDirections::Inbound | BlockDirections::Both)
135    }
136
137    fn is_writable(&self) -> bool {
138        matches!(self, BlockDirections::Outbound | BlockDirections::Both)
139    }
140}
141
142#[cfg(test)]
143mod tests {
144    use super::*;
145
146    #[test]
147    fn test_block_directions_ext() {
148        assert!(!BlockDirections::None.is_readable());
149        assert!(!BlockDirections::None.is_writable());
150        assert!(BlockDirections::Inbound.is_readable());
151        assert!(!BlockDirections::Inbound.is_writable());
152        assert!(!BlockDirections::Outbound.is_readable());
153        assert!(BlockDirections::Outbound.is_writable());
154        assert!(BlockDirections::Both.is_readable());
155        assert!(BlockDirections::Both.is_writable());
156    }
157}