1use std::io::{self, Read, Write};
9use std::fmt;
10
11use rand::{self, Rng};
12use rand::prelude::ThreadRng;
13
14#[derive(Default, Debug)]
18pub struct ClientRequest {
19 boundary: Option<String>,
20 content_len: Option<u64>,
21}
22
23#[cfg(feature = "client")]
24impl ::client::HttpRequest for ClientRequest {
25 type Stream = HttpBuffer;
26 type Error = io::Error;
27
28 fn apply_headers(&mut self, boundary: &str, content_len: Option<u64>) -> bool {
29 self.boundary = Some(boundary.into());
30 self.content_len = content_len;
31 true
32 }
33
34 fn open_stream(self) -> Result<HttpBuffer, io::Error> {
37 debug!("ClientRequest::open_stream called! {:?}", self);
38 let boundary = self.boundary.expect("ClientRequest::set_headers() was not called!");
39
40 Ok(HttpBuffer::new_empty(boundary, self.content_len))
41 }
42}
43
44
45pub struct HttpBuffer {
49 pub buf: Vec<u8>,
51 pub boundary: String,
53 pub content_len: Option<u64>,
55 rng: ThreadRng,
56}
57
58impl HttpBuffer {
59 pub fn new_empty(boundary: String, content_len: Option<u64>) -> HttpBuffer {
61 Self::with_buf(Vec::new(), boundary, content_len)
62 }
63
64 pub fn with_buf(buf: Vec<u8>, boundary: String, content_len: Option<u64>) -> Self {
66 HttpBuffer {
67 buf,
68 boundary,
69 content_len,
70 rng: rand::thread_rng()
71 }
72 }
73
74 pub fn for_server(&self) -> ServerRequest {
76 ServerRequest {
77 data: &self.buf,
78 boundary: &self.boundary,
79 content_len: self.content_len,
80 rng: rand::thread_rng(),
81 }
82 }
83}
84
85impl Write for HttpBuffer {
86 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
89 if buf.is_empty() {
90 debug!("HttpBuffer::write() was passed a zero-sized buffer.");
91 return Ok(0);
92 }
93
94 let len = self.rng.gen_range(1, buf.len() + 1);
96
97 self.buf.write(&buf[..len])
98 }
99
100 fn flush(&mut self) -> io::Result<()> {
101 self.buf.flush()
102 }
103}
104
105#[cfg(feature = "client")]
106impl ::client::HttpStream for HttpBuffer {
107 type Request = ClientRequest;
108 type Response = HttpBuffer;
109 type Error = io::Error;
110
111 fn finish(self) -> Result<Self, io::Error> { Ok(self) }
113}
114
115impl fmt::Debug for HttpBuffer {
116 fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
117 f.debug_struct("multipart::mock::HttpBuffer")
118 .field("buf", &self.buf)
119 .field("boundary", &self.boundary)
120 .field("content_len", &self.content_len)
121 .finish()
122 }
123}
124
125pub struct ServerRequest<'a> {
129 pub data: &'a [u8],
131 pub boundary: &'a str,
133 pub content_len: Option<u64>,
135 rng: ThreadRng,
136}
137
138impl<'a> ServerRequest<'a> {
139 pub fn new(data: &'a [u8], boundary: &'a str) -> Self {
143 ServerRequest {
144 data,
145 boundary,
146 content_len: None,
147 rng: rand::thread_rng(),
148 }
149 }
150}
151
152impl<'a> Read for ServerRequest<'a> {
153 fn read(&mut self, out: &mut [u8]) -> io::Result<usize> {
156 if out.is_empty() {
157 debug!("ServerRequest::read() was passed a zero-sized buffer.");
158 return Ok(0);
159 }
160
161 let len = self.rng.gen_range(1, out.len() + 1);
163 self.data.read(&mut out[..len])
164 }
165}
166
167#[cfg(feature = "server")]
168impl<'a> ::server::HttpRequest for ServerRequest<'a> {
169 type Body = Self;
170
171 fn multipart_boundary(&self) -> Option<&str> { Some(self.boundary) }
172
173 fn body(self) -> Self::Body {
174 self
175 }
176}
177
178pub struct StdoutTee<'s, W> {
180 inner: W,
181 stdout: io::StdoutLock<'s>,
182}
183
184impl<'s, W> StdoutTee<'s, W> {
185 pub fn new(inner: W, stdout: &'s io::Stdout) -> Self {
187 Self {
188 inner, stdout: stdout.lock(),
189 }
190 }
191}
192
193impl<'s, W: Write> Write for StdoutTee<'s, W> {
194 fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
195 self.inner.write_all(buf)?;
196 self.stdout.write(buf)
197 }
198
199 fn flush(&mut self) -> io::Result<()> {
200 self.inner.flush()?;
201 self.stdout.flush()
202 }
203}