1use std::fmt;
8#[cfg(any(feature = "blocking", feature = "tokio"))]
9use std::sync::Arc;
10
11use crate::backend::ConPtyBackend;
12#[cfg(any(feature = "blocking", feature = "tokio"))]
13use crate::core::session::Session as SessionCore;
14use crate::error::Result;
15use crate::size::Size;
16use crate::status::ExitStatus;
17
18#[derive(Debug, Clone, Default)]
24pub struct SessionOptions {
25 size: Size,
26 backend: Option<ConPtyBackend>,
27}
28
29impl SessionOptions {
30 #[must_use]
32 pub fn new() -> Self {
33 Self::default()
34 }
35
36 #[must_use]
38 pub const fn size(mut self, size: Size) -> Self {
39 self.size = size;
40 self
41 }
42
43 #[must_use]
45 pub fn backend(mut self, backend: ConPtyBackend) -> Self {
46 self.backend = Some(backend);
47 self
48 }
49
50 #[cfg(any(feature = "blocking", feature = "tokio"))]
51 #[must_use]
52 pub(super) fn into_parts(self) -> (Size, Option<ConPtyBackend>) {
53 (self.size, self.backend)
54 }
55}
56
57pub struct SessionOutput {
72 status: ExitStatus,
73 bytes: Vec<u8>,
74}
75
76impl SessionOutput {
77 #[cfg(any(feature = "blocking", feature = "tokio"))]
78 #[must_use]
79 pub(super) const fn new(status: ExitStatus, bytes: Vec<u8>) -> Self {
80 Self { status, bytes }
81 }
82
83 #[must_use]
85 pub const fn status(&self) -> ExitStatus {
86 self.status
87 }
88
89 #[must_use]
91 pub fn as_bytes(&self) -> &[u8] {
92 &self.bytes
93 }
94
95 #[must_use]
97 pub fn into_bytes(self) -> Vec<u8> {
98 self.bytes
99 }
100}
101
102impl fmt::Debug for SessionOutput {
103 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
104 f.debug_struct("SessionOutput")
105 .field("status", &self.status)
106 .field("bytes", &format_args!("{} bytes", self.bytes.len()))
107 .finish()
108 }
109}
110
111#[derive(Clone)]
117pub struct PtyController {
118 #[cfg(any(feature = "blocking", feature = "tokio"))]
119 pub(super) inner: Arc<SessionCore>,
120 #[cfg(not(any(feature = "blocking", feature = "tokio")))]
121 uninhabited: std::convert::Infallible,
122}
123
124impl PtyController {
125 #[cfg(any(feature = "blocking", feature = "tokio"))]
126 pub(super) const fn new(inner: Arc<SessionCore>) -> Self {
127 Self { inner }
128 }
129}
130
131#[cfg(any(feature = "blocking", feature = "tokio"))]
132impl PtyController {
133 pub fn resize(&self, size: Size) -> Result<()> {
140 self.inner.resize(size)
141 }
142
143 #[must_use]
145 pub fn size(&self) -> Size {
146 self.inner.size()
147 }
148
149 pub fn clear(&self) -> Result<()> {
157 self.inner.clear()
158 }
159
160 #[must_use]
162 pub fn supports_clear(&self) -> bool {
163 self.inner.supports_clear()
164 }
165
166 #[must_use]
167 #[cfg(test)]
168 pub(crate) fn supports_release(&self) -> bool {
169 self.inner.supports_release()
170 }
171
172 #[must_use]
173 #[cfg(test)]
174 pub(crate) fn reader_finished(&self) -> bool {
175 self.inner.reader_finished()
176 }
177
178 #[must_use]
179 #[cfg(test)]
180 pub(crate) fn backend_kind(&self) -> &crate::backend::BackendKind {
181 self.inner.backend_kind()
182 }
183}
184
185#[cfg(any(feature = "blocking", feature = "tokio"))]
186impl fmt::Debug for PtyController {
187 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
188 f.debug_struct("PtyController")
189 .field("size", &self.inner.size())
190 .field("supports_clear", &self.inner.supports_clear())
191 .finish_non_exhaustive()
192 }
193}