Skip to content

Commit d394025

Browse files
committed
progress on multipart
1 parent 22260cd commit d394025

File tree

5 files changed

+44
-75
lines changed

5 files changed

+44
-75
lines changed

Cargo.toml

-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,6 @@ anyhow = "1.0.26"
3939
# features: cookies
4040
cookie = { version = "0.14.0", features = ["percent-encode"], optional = true }
4141
futures-core = "0.3.5"
42-
futures-util = "0.3.7"
4342
infer = "0.2.3"
4443
pin-project-lite = "0.2.0"
4544
url = { version = "2.1.1", features = ["serde"] }

src/body.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ pin_project_lite::pin_project! {
5656
reader: Box<dyn AsyncBufRead + Unpin + Send + Sync + 'static>,
5757
mime: Mime,
5858
length: Option<usize>,
59-
bytes_read: usize
59+
bytes_read: usize,
6060
pub(crate) file_name: Option<String>,
6161
}
6262
}

src/lib.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -124,17 +124,14 @@ pub mod conditional;
124124
pub mod content;
125125
pub mod headers;
126126
pub mod mime;
127+
pub mod multipart;
127128
pub mod other;
128129
pub mod proxies;
129130
pub mod server;
130131
pub mod trace;
131132
pub mod transfer;
132133
pub mod upgrade;
133134

134-
cfg_unstable! {
135-
pub mod multipart;
136-
}
137-
138135
mod body;
139136
mod error;
140137
mod extensions;

src/multipart/mod.rs

+29-69
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,15 @@
11
//! Multipart/form-data types.
22
//!
3+
//! # Specifications
4+
//!
5+
//! [RFC 2046, section 5.1: Multipart Media Type](https://tools.ietf.org/html/rfc2046#section-5.1)
6+
//! [RFC 2388: Returning Values from Forms: multipart/form-data](https://tools.ietf.org/html/rfc2388)
7+
//! [RFC 7578: Returning Values from Forms: multipart/form-data](https://tools.ietf.org/html/rfc7578)
8+
//!
39
//! # Examples
410
//!
511
//! Request:
12+
//!
613
//! ```
714
//! use http_types::multipart::{Multipart, Entry};
815
//!
@@ -27,7 +34,7 @@
2734
//! let mut entries = res.body_multipart();
2835
//! while let Some(entry) = entries.await {
2936
//! println!("name: {}", entry.name());
30-
//! println!("data: {}", entry.into_string()?);
37+
//! println!("data: {}", entry.into_string().await?);
3138
//! }
3239
//! ```
3340
@@ -38,7 +45,6 @@ use std::{fmt::Debug, pin::Pin, str::FromStr};
3845

3946
use futures_core::stream::Stream;
4047
use futures_lite::{io, prelude::*};
41-
use futures_util::stream::TryStreamExt;
4248
use multipart::server::Multipart as Parser;
4349

4450
use crate::mime;
@@ -133,7 +139,9 @@ impl Stream for Multipart {
133139
if let Some(mime) = mime {
134140
entry.set_mime(mime);
135141
} else {
136-
// https://tools.ietf.org/html/rfc7578#section-4.4
142+
// Each part MAY have an (optional) "Content-Type" header
143+
// field, which defaults to "text/plain".
144+
// src: https://tools.ietf.org/html/rfc7578#section-4.4
137145
entry.set_mime(mime::PLAIN);
138146
}
139147

@@ -149,83 +157,35 @@ impl Stream for Multipart {
149157
}
150158
}
151159

152-
// struct MultipartReader {
153-
// entry_iter: Box<dyn Iterator<Item = Entry>>,
154-
// }
155-
156-
// impl From<Multipart> for MultipartReader {
157-
// fn from(multipart: Multipart) -> Self {
158-
// Self {
159-
// entry_iter: Box::new(multipart.entries.into_iter())
160-
// }
161-
// }
162-
// }
163-
164-
// impl AsyncRead for MultipartReader {
165-
// #[allow(missing_doc_code_examples)]
166-
// fn poll_read(
167-
// mut self: Pin<&mut Self>,
168-
// cx: &mut Context<'_>,
169-
// buf: &mut [u8],
170-
// ) -> Poll<io::Result<usize>> {
171-
// if let Some(entry) = self.entry_iter.next() {
172-
// Pin::new(&mut entry).poll_read(cx, buf)
173-
// } else {
174-
// Poll::Ready()
175-
// }
176-
// }
177-
// }
178-
179-
// impl AsyncBufRead for MultipartReader {
180-
// #[allow(missing_doc_code_examples)]
181-
// fn poll_fill_buf(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&'_ [u8]>> {
182-
// let this = self.project();
183-
// this.reader.poll_fill_buf(cx)
184-
// }
185-
186-
// fn consume(mut self: Pin<&mut Self>, amt: usize) {
187-
// Pin::new(&mut self.reader).consume(amt)
188-
// }
189-
// }
190-
191-
// We need AsRef<[u8]> on BufReader for TryStreamExt (into_async_read) so... wrap and patch it in ourselves, for now.
192-
#[doc(hidden)]
193-
#[derive(Debug)]
194-
pub struct BufReader<R: AsyncRead> {
195-
inner: io::BufReader<R>,
160+
struct MultipartReader {
161+
entry_iter: Box<dyn Iterator<Item = Entry>>,
196162
}
197163

198-
#[doc(hidden)]
199-
impl<R: AsyncRead> BufReader<R> {
200-
#[allow(missing_doc_code_examples)]
201-
#[doc(hidden)]
202-
pub fn new(inner: R) -> Self {
164+
impl From<Multipart> for MultipartReader {
165+
fn from(multipart: Multipart) -> Self {
203166
Self {
204-
inner: io::BufReader::new(inner),
167+
entry_iter: Box::new(multipart.entries.into_iter()),
205168
}
206169
}
207170
}
208171

209-
#[doc(hidden)]
210-
impl<R: AsyncRead> AsRef<[u8]> for BufReader<R> {
172+
impl AsyncRead for MultipartReader {
211173
#[allow(missing_doc_code_examples)]
212-
#[doc(hidden)]
213-
fn as_ref(&self) -> &[u8] {
214-
self.inner.buffer()
174+
fn poll_read(
175+
mut self: Pin<&mut Self>,
176+
cx: &mut Context<'_>,
177+
buf: &mut [u8],
178+
) -> Poll<io::Result<usize>> {
179+
if let Some(mut entry) = self.entry_iter.next() {
180+
Pin::new(&mut entry).poll_read(cx, buf)
181+
} else {
182+
todo!();
183+
}
215184
}
216185
}
217186

218187
impl From<Multipart> for Body {
219-
fn from(multipart: Multipart) -> Self {
220-
let stream = multipart.map(|maybe_entry| {
221-
maybe_entry
222-
.map(BufReader::new)
223-
.map_err(|err| {
224-
std::io::Error::new(std::io::ErrorKind::Other, err.to_string())
225-
})
226-
});
227-
let mut body = Body::from_reader(io::BufReader::new(stream.into_async_read()), None);
228-
body.set_mime(mime::MULTIPART_FORM);
229-
body
188+
fn from(_multipart: Multipart) -> Self {
189+
todo!();
230190
}
231191
}

src/utils/mod.rs

+13
Original file line numberDiff line numberDiff line change
@@ -40,3 +40,16 @@ pub(crate) fn sort_by_weight<T: PartialOrd + Clone>(props: &mut Vec<T>) {
4040
});
4141
*props = arr.into_iter().map(|(_, t)| t).collect::<Vec<T>>();
4242
}
43+
44+
/// Declares unstable items.
45+
#[allow(dead_code)]
46+
#[doc(hidden)]
47+
macro_rules! cfg_unstable {
48+
($($item:item)*) => {
49+
$(
50+
#[cfg(feature = "unstable")]
51+
#[cfg_attr(feature = "docs", doc(cfg(unstable)))]
52+
$item
53+
)*
54+
}
55+
}

0 commit comments

Comments
 (0)