1#![allow(clippy::std_instead_of_core)] use std::io::{BufRead, IoSlice, Read, Result, Write};
3
4use rustls::{Connection, VecInput};
5
6use crate::complete_io;
7
8#[expect(clippy::exhaustive_structs)]
17#[derive(Debug)]
18pub struct Stream<'a, C: 'a + ?Sized, T: 'a + Read + Write + ?Sized> {
19 pub conn: &'a mut C,
21
22 pub sock: &'a mut T,
24
25 pub input: &'a mut VecInput,
27}
28
29impl<'a, C, T> Stream<'a, C, T>
30where
31 C: 'a + Connection,
32 T: 'a + Read + Write,
33{
34 pub fn new(input: &'a mut VecInput, conn: &'a mut C, sock: &'a mut T) -> Self {
37 Self { conn, sock, input }
38 }
39
40 fn complete_prior_io(&mut self) -> Result<()> {
43 if self.conn.is_handshaking() {
44 complete_io(self.sock, self.input, self.conn)?;
45 }
46
47 if self.conn.wants_write() {
48 complete_io(self.sock, self.input, self.conn)?;
49 }
50
51 Ok(())
52 }
53
54 fn prepare_read(&mut self) -> Result<()> {
55 self.complete_prior_io()?;
56
57 while self.conn.wants_read() {
62 if complete_io(self.sock, self.input, self.conn)?.0 == 0 {
63 break;
64 }
65 }
66
67 Ok(())
68 }
69
70 fn fill_buf(mut self) -> Result<&'a [u8]> {
72 self.prepare_read()?;
73 self.conn.reader().into_first_chunk()
74 }
75}
76
77impl<'a, C, T> Read for Stream<'a, C, T>
78where
79 C: 'a + Connection,
80 T: 'a + Read + Write,
81{
82 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
83 self.prepare_read()?;
84 self.conn.reader().read(buf)
85 }
86}
87
88impl<'a, C, T> BufRead for Stream<'a, C, T>
89where
90 C: 'a + Connection,
91 T: 'a + Read + Write,
92{
93 fn fill_buf(&mut self) -> Result<&[u8]> {
94 Stream {
96 conn: self.conn,
97 sock: self.sock,
98 input: self.input,
99 }
100 .fill_buf()
101 }
102
103 fn consume(&mut self, amt: usize) {
104 self.conn.reader().consume(amt)
105 }
106}
107
108impl<'a, C, T> Write for Stream<'a, C, T>
109where
110 C: 'a + Connection,
111 T: 'a + Read + Write,
112{
113 fn write(&mut self, buf: &[u8]) -> Result<usize> {
114 self.complete_prior_io()?;
115
116 let len = self.conn.writer().write(buf)?;
117
118 let _ = complete_io(self.sock, self.input, self.conn);
122
123 Ok(len)
124 }
125
126 fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> Result<usize> {
127 self.complete_prior_io()?;
128
129 let len = self
130 .conn
131 .writer()
132 .write_vectored(bufs)?;
133
134 let _ = complete_io(self.sock, self.input, self.conn);
138
139 Ok(len)
140 }
141
142 fn flush(&mut self) -> Result<()> {
143 self.complete_prior_io()?;
144
145 self.conn.writer().flush()?;
146 if self.conn.wants_write() {
147 complete_io(self.sock, self.input, self.conn)?;
148 }
149 Ok(())
150 }
151}
152
153#[expect(clippy::exhaustive_structs)]
162#[derive(Debug)]
163pub struct StreamOwned<C: Sized, T: Read + Write + Sized> {
164 pub conn: C,
166
167 pub sock: T,
169
170 pub input: VecInput,
172}
173
174impl<C, T> StreamOwned<C, T>
175where
176 C: Connection,
177 T: Read + Write,
178{
179 pub fn new(conn: C, sock: T) -> Self {
185 Self {
186 conn,
187 sock,
188 input: VecInput::default(),
189 }
190 }
191
192 pub fn get_ref(&self) -> &T {
194 &self.sock
195 }
196
197 pub fn get_mut(&mut self) -> &mut T {
199 &mut self.sock
200 }
201
202 pub fn into_parts(self) -> (C, T) {
204 (self.conn, self.sock)
205 }
206}
207
208impl<'a, C, T> StreamOwned<C, T>
209where
210 C: Connection,
211 T: Read + Write,
212{
213 fn as_stream(&'a mut self) -> Stream<'a, C, T> {
214 Stream {
215 conn: &mut self.conn,
216 sock: &mut self.sock,
217 input: &mut self.input,
218 }
219 }
220}
221
222impl<C, T> Read for StreamOwned<C, T>
223where
224 C: Connection,
225 T: Read + Write,
226{
227 fn read(&mut self, buf: &mut [u8]) -> Result<usize> {
228 self.as_stream().read(buf)
229 }
230}
231
232impl<C, T> BufRead for StreamOwned<C, T>
233where
234 C: Connection,
235 T: Read + Write,
236{
237 fn fill_buf(&mut self) -> Result<&[u8]> {
238 self.as_stream().fill_buf()
239 }
240
241 fn consume(&mut self, amt: usize) {
242 self.as_stream().consume(amt)
243 }
244}
245
246impl<C, T> Write for StreamOwned<C, T>
247where
248 C: Connection,
249 T: Read + Write,
250{
251 fn write(&mut self, buf: &[u8]) -> Result<usize> {
252 self.as_stream().write(buf)
253 }
254
255 fn flush(&mut self) -> Result<()> {
256 self.as_stream().flush()
257 }
258}
259
260#[cfg(test)]
261mod tests {
262 use std::net::TcpStream;
263
264 use rustls::{ClientConnection, ServerConnection};
265
266 use super::{Stream, StreamOwned};
267
268 #[test]
269 fn stream_can_be_created_for_connection_and_tcpstream() {
270 type _Test<'a> = Stream<'a, ClientConnection, TcpStream>;
271 }
272
273 #[test]
274 fn streamowned_can_be_created_for_client_and_tcpstream() {
275 type _Test = StreamOwned<ClientConnection, TcpStream>;
276 }
277
278 #[test]
279 fn streamowned_can_be_created_for_server_and_tcpstream() {
280 type _Test = StreamOwned<ServerConnection, TcpStream>;
281 }
282}