1use std::{
2 cmp::min,
3 io::{self, Read, Write},
4 net::TcpStream,
5 time::Duration,
6};
7
8#[derive(Debug)]
9struct StringStream(Vec<u8>, usize);
10
11impl Read for StringStream {
12 fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
13 let n = self.peek(buf)?;
14 self.1 += n;
15 Ok(n)
16 }
17}
18
19impl StringStream {
20 fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
21 if self.1 >= self.0.len() {
22 return Err(io::Error::new(io::ErrorKind::WouldBlock, ""));
23 }
24 let src = &self.0[self.1..];
25 let n = min(buf.len(), src.len());
26 buf[..n].copy_from_slice(src);
27 Ok(n)
28 }
29}
30
31#[derive(Debug)]
32enum HttpStreamInner {
33 Tcp(TcpStream),
34 String(StringStream, Vec<u8>),
35 Dummy,
36}
37
38#[derive(Debug)]
71pub struct HttpStream {
72 inner: HttpStreamInner,
73}
74
75impl HttpStream {
76 pub fn set_read_timeout(&self, d: Option<Duration>) -> io::Result<()> {
77 match &self.inner {
78 HttpStreamInner::Tcp(tcp_stream) => tcp_stream.set_read_timeout(d),
79 HttpStreamInner::Dummy | HttpStreamInner::String(..) => Ok(()),
80 }
81 }
82 pub fn peek(&self, buf: &mut [u8]) -> std::io::Result<usize> {
83 match &self.inner {
84 HttpStreamInner::Tcp(tcp_stream) => tcp_stream.peek(buf),
85 HttpStreamInner::Dummy => Ok(0),
86 HttpStreamInner::String(read, _) => read.peek(buf),
87 }
88 }
89}
90
91impl Read for HttpStream {
92 fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
93 match &mut self.inner {
94 HttpStreamInner::Tcp(tcp_stream) => tcp_stream.read(buf),
95 HttpStreamInner::Dummy => Ok(0),
96 HttpStreamInner::String(buf_reader, _) => buf_reader.read(buf),
97 }
98 }
99}
100
101impl Write for HttpStream {
102 fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
103 match &mut self.inner {
104 HttpStreamInner::Tcp(tcp_stream) => tcp_stream.write(buf),
105 HttpStreamInner::Dummy => Ok(0),
106 HttpStreamInner::String(_, w) => w.write(buf),
107 }
108 }
109
110 fn flush(&mut self) -> std::io::Result<()> {
111 match &mut self.inner {
112 HttpStreamInner::Tcp(tcp_stream) => tcp_stream.flush(),
113 HttpStreamInner::Dummy | HttpStreamInner::String(..) => Ok(()),
114 }
115 }
116}
117
118impl From<TcpStream> for HttpStream {
119 fn from(value: TcpStream) -> Self {
120 Self {
121 inner: HttpStreamInner::Tcp(value),
122 }
123 }
124}
125
126impl From<String> for HttpStream {
127 fn from(value: String) -> Self {
128 let src_vec = value.into_bytes();
129 let stream = StringStream(src_vec, 0);
130 Self {
131 inner: HttpStreamInner::String(stream, Vec::new()),
132 }
133 }
134}
135
136impl<'a> From<&'a str> for HttpStream {
137 fn from(value: &'a str) -> Self {
138 Self::from(value.to_string())
139 }
140}
141
142impl HttpStream {
143 #[must_use]
144 pub fn dummy() -> Self {
145 Self {
146 inner: HttpStreamInner::Dummy,
147 }
148 }
149}