Skip to content

Commit e7920bf

Browse files
committed
Add conversions to and from bytes
1 parent 9ab6f9b commit e7920bf

File tree

3 files changed

+100
-2
lines changed

3 files changed

+100
-2
lines changed

src/body.rs

Lines changed: 49 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use async_std::io::prelude::*;
12
use async_std::io::{self, BufRead, Read};
23

34
use std::fmt::{self, Debug};
@@ -81,7 +82,7 @@ impl Body {
8182

8283
/// Create a `Body` from a reader with an optional length.
8384
///
84-
/// The Mime type set to `application/octet-stream` if no other mime type has been set or can
85+
/// The Mime type is set to `application/octet-stream` if no other mime type has been set or can
8586
/// be sniffed. If a `Body` has no length, HTTP implementations will often switch over to
8687
/// framed messages such as [Chunked
8788
/// Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding).
@@ -109,6 +110,53 @@ impl Body {
109110
}
110111
}
111112

113+
/// Create a `Body` from a Vec of bytes.
114+
///
115+
/// The Mime type is set to `application/octet-stream` if no other mime type has been set or can
116+
/// be sniffed. If a `Body` has no length, HTTP implementations will often switch over to
117+
/// framed messages such as [Chunked
118+
/// Encoding](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Transfer-Encoding).
119+
///
120+
/// # Examples
121+
///
122+
/// ```
123+
/// use http_types::{Body, Response, StatusCode};
124+
/// use async_std::io::Cursor;
125+
///
126+
/// let mut req = Response::new(StatusCode::Ok);
127+
///
128+
/// let input = vec![1, 2, 3];
129+
/// req.set_body(Body::from_bytes(input));
130+
/// ```
131+
pub fn from_bytes(bytes: Vec<u8>) -> Self {
132+
Self {
133+
mime: mime::BYTE_STREAM,
134+
length: Some(bytes.len()),
135+
reader: Box::new(io::Cursor::new(bytes)),
136+
}
137+
}
138+
139+
/// Parse the body into a `Vec<u8>`.
140+
///
141+
/// # Examples
142+
///
143+
/// ```
144+
/// # fn main() -> Result<(), http_types::Error> { async_std::task::block_on(async {
145+
/// use http_types::Body;
146+
///
147+
/// let bytes = vec![1, 2, 3];
148+
/// let body = Body::from_bytes(bytes);
149+
///
150+
/// let bytes: Vec<u8> = body.into_bytes().await?;
151+
/// assert_eq!(bytes, vec![1, 2, 3]);
152+
/// # Ok(()) }) }
153+
/// ```
154+
pub async fn into_bytes(mut self) -> crate::Result<Vec<u8>> {
155+
let mut buf = Vec::with_capacity(1024);
156+
self.read_to_end(&mut buf).await?;
157+
Ok(buf)
158+
}
159+
112160
/// Get the length of the body in bytes.
113161
///
114162
/// # Examples
@@ -165,7 +213,6 @@ impl Body {
165213
/// # Ok(()) }) }
166214
/// ```
167215
pub async fn into_string(mut self) -> io::Result<String> {
168-
use async_std::io::ReadExt;
169216
let mut result = String::with_capacity(self.len().unwrap_or(0));
170217
self.read_to_string(&mut result).await?;
171218
Ok(result)

src/request.rs

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -226,6 +226,31 @@ impl Request {
226226
self.body.into_string().await
227227
}
228228

229+
/// Read the body as bytes.
230+
///
231+
/// This consumes the `Request`. If you want to read the body without
232+
/// consuming the request, consider using the `take_body` method and
233+
/// then calling `Body::into_bytes` or using the Request's AsyncRead
234+
/// implementation to read the body.
235+
///
236+
/// # Examples
237+
///
238+
/// ```
239+
/// # fn main() -> Result<(), http_types::Error> { async_std::task::block_on(async {
240+
/// use http_types::{Body, Url, Method, Request};
241+
///
242+
/// let bytes = vec![1, 2, 3];
243+
/// let mut req = Request::new(Method::Get, Url::parse("https://example.com").unwrap());
244+
/// req.set_body(Body::from_bytes(bytes));
245+
///
246+
/// let bytes = req.body_bytes().await?;
247+
/// assert_eq!(bytes, vec![1, 2, 3]);
248+
/// # Ok(()) }) }
249+
/// ```
250+
pub async fn body_bytes(self) -> crate::Result<Vec<u8>> {
251+
self.body.into_bytes().await
252+
}
253+
229254
/// Get an HTTP header.
230255
pub fn header(&self, name: &HeaderName) -> Option<&Vec<HeaderValue>> {
231256
self.headers.get(name)

src/response.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -254,6 +254,32 @@ impl Response {
254254
self.body.into_string().await
255255
}
256256

257+
/// Read the body as bytes.
258+
///
259+
/// This consumes the `Response`. If you want to read the body without
260+
/// consuming the response, consider using the `take_body` method and
261+
/// then calling `Body::into_bytes` or using the Response's AsyncRead
262+
/// implementation to read the body.
263+
///
264+
/// # Examples
265+
///
266+
/// ```
267+
/// # fn main() -> Result<(), http_types::Error> { async_std::task::block_on(async {
268+
///
269+
/// use http_types::{Body, Url, Method, Response, StatusCode};
270+
///
271+
/// let bytes = vec![1, 2, 3];
272+
/// let mut res = Response::new(StatusCode::Ok);
273+
/// res.set_body(Body::from_bytes(bytes));
274+
///
275+
/// let bytes = res.body_bytes().await?;
276+
/// assert_eq!(bytes, vec![1, 2, 3]);
277+
/// # Ok(()) }) }
278+
/// ```
279+
pub async fn body_bytes(self) -> crate::Result<Vec<u8>> {
280+
self.body.into_bytes().await
281+
}
282+
257283
/// Set the response MIME.
258284
pub fn set_content_type(&mut self, mime: Mime) -> Option<Vec<HeaderValue>> {
259285
let value: HeaderValue = mime.into();

0 commit comments

Comments
 (0)