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)]
36pub struct SessionOptions {
37 size: Size,
38 backend: Option<ConPtyBackend>,
39}
40
41impl SessionOptions {
42 #[must_use]
44 pub fn new() -> Self {
45 Self::default()
46 }
47
48 #[must_use]
50 pub const fn size(mut self, size: Size) -> Self {
51 self.size = size;
52 self
53 }
54
55 #[must_use]
57 pub fn backend(mut self, backend: ConPtyBackend) -> Self {
58 self.backend = Some(backend);
59 self
60 }
61
62 #[cfg(any(feature = "blocking", feature = "tokio"))]
63 #[must_use]
64 pub(super) fn into_parts(self) -> (Size, Option<ConPtyBackend>) {
65 (self.size, self.backend)
66 }
67}
68
69pub struct SessionOutput {
78 status: ExitStatus,
79 bytes: Vec<u8>,
80}
81
82impl SessionOutput {
83 #[cfg(any(feature = "blocking", feature = "tokio"))]
84 #[must_use]
85 pub(super) const fn new(status: ExitStatus, bytes: Vec<u8>) -> Self {
86 Self { status, bytes }
87 }
88
89 #[must_use]
91 pub const fn status(&self) -> ExitStatus {
92 self.status
93 }
94
95 #[must_use]
97 pub fn as_bytes(&self) -> &[u8] {
98 &self.bytes
99 }
100
101 #[must_use]
103 pub fn into_bytes(self) -> Vec<u8> {
104 self.bytes
105 }
106}
107
108impl fmt::Debug for SessionOutput {
109 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
110 f.debug_struct("SessionOutput")
111 .field("status", &self.status)
112 .field("bytes", &format_args!("{} bytes", self.bytes.len()))
113 .finish()
114 }
115}
116
117#[derive(Clone)]
123pub struct PtyController {
124 #[cfg(any(feature = "blocking", feature = "tokio"))]
125 pub(super) inner: Arc<SessionCore>,
126 #[cfg(not(any(feature = "blocking", feature = "tokio")))]
127 uninhabited: std::convert::Infallible,
128}
129
130impl PtyController {
131 #[cfg(any(feature = "blocking", feature = "tokio"))]
132 pub(super) const fn new(inner: Arc<SessionCore>) -> Self {
133 Self { inner }
134 }
135}
136
137#[cfg(any(feature = "blocking", feature = "tokio"))]
138impl PtyController {
139 pub fn resize(&self, size: Size) -> Result<()> {
146 self.inner.resize(size)
147 }
148
149 #[must_use]
151 pub fn size(&self) -> Size {
152 self.inner.size()
153 }
154
155 pub fn clear(&self) -> Result<()> {
163 self.inner.clear()
164 }
165
166 #[must_use]
168 pub fn supports_clear(&self) -> bool {
169 self.inner.supports_clear()
170 }
171
172 #[must_use]
173 #[cfg(test)]
174 pub(crate) fn supports_release(&self) -> bool {
175 self.inner.supports_release()
176 }
177
178 #[must_use]
179 #[cfg(test)]
180 pub(crate) fn reader_finished(&self) -> bool {
181 self.inner.reader_finished()
182 }
183
184 #[must_use]
185 #[cfg(test)]
186 pub(crate) fn backend_kind(&self) -> &crate::backend::BackendKind {
187 self.inner.backend_kind()
188 }
189}
190
191#[cfg(any(feature = "blocking", feature = "tokio"))]
192impl fmt::Debug for PtyController {
193 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
194 f.debug_struct("PtyController")
195 .field("size", &self.inner.size())
196 .field("supports_clear", &self.inner.supports_clear())
197 .finish_non_exhaustive()
198 }
199}
200
201#[cfg(doctest)]
210mod api_boundary {}