Skip to content

Commit 22260cd

Browse files
committed
Init multipart
more multipart multipart parsing Fix Entry::from_file compiling impl From<Multipart> for Body more multipart progress...
1 parent f955922 commit 22260cd

File tree

5 files changed

+411
-1
lines changed

5 files changed

+411
-1
lines changed

Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,8 @@ anyhow = "1.0.26"
3838

3939
# features: cookies
4040
cookie = { version = "0.14.0", features = ["percent-encode"], optional = true }
41+
futures-core = "0.3.5"
42+
futures-util = "0.3.7"
4143
infer = "0.2.3"
4244
pin-project-lite = "0.2.0"
4345
url = { version = "2.1.1", features = ["serde"] }
@@ -47,6 +49,7 @@ serde_urlencoded = "0.7.0"
4749
rand = "0.7.3"
4850
serde_qs = "0.7.0"
4951
base64 = "0.13.0"
52+
multipart = { version = "0.17.0", default-features = false, features = ["server"] }
5053

5154
[dev-dependencies]
5255
http = "0.2.0"

src/body.rs

+22-1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@ pin_project_lite::pin_project! {
5757
mime: Mime,
5858
length: Option<usize>,
5959
bytes_read: usize
60+
pub(crate) file_name: Option<String>,
6061
}
6162
}
6263

@@ -80,6 +81,7 @@ impl Body {
8081
mime: mime::BYTE_STREAM,
8182
length: Some(0),
8283
bytes_read: 0,
84+
file_name: None,
8385
}
8486
}
8587

@@ -111,6 +113,7 @@ impl Body {
111113
mime: mime::BYTE_STREAM,
112114
length: len,
113115
bytes_read: 0,
116+
file_name: None,
114117
}
115118
}
116119

@@ -155,6 +158,7 @@ impl Body {
155158
length: Some(bytes.len()),
156159
reader: Box::new(io::Cursor::new(bytes)),
157160
bytes_read: 0,
161+
file_name: None,
158162
}
159163
}
160164

@@ -205,6 +209,7 @@ impl Body {
205209
length: Some(s.len()),
206210
reader: Box::new(io::Cursor::new(s.into_bytes())),
207211
bytes_read: 0,
212+
file_name: None,
208213
}
209214
}
210215

@@ -251,6 +256,7 @@ impl Body {
251256
reader: Box::new(io::Cursor::new(bytes)),
252257
mime: mime::JSON,
253258
bytes_read: 0,
259+
file_name: None,
254260
};
255261
Ok(body)
256262
}
@@ -316,6 +322,7 @@ impl Body {
316322
reader: Box::new(io::Cursor::new(bytes)),
317323
mime: mime::FORM,
318324
bytes_read: 0,
325+
file_name: None,
319326
};
320327
Ok(body)
321328
}
@@ -370,7 +377,7 @@ impl Body {
370377
P: AsRef<std::path::Path>,
371378
{
372379
let path = path.as_ref();
373-
let mut file = async_std::fs::File::open(path).await?;
380+
let mut file = async_std::fs::File::open(&path).await?;
374381
let len = file.metadata().await?.len();
375382

376383
// Look at magic bytes first, look at extension second, fall back to
@@ -385,6 +392,7 @@ impl Body {
385392
length: Some(len as usize),
386393
reader: Box::new(io::BufReader::new(file)),
387394
bytes_read: 0,
395+
file_name: Some(path.to_string_lossy().to_string()),
388396
})
389397
}
390398

@@ -419,6 +427,19 @@ impl Body {
419427
pub fn set_mime(&mut self, mime: impl Into<Mime>) {
420428
self.mime = mime.into();
421429
}
430+
431+
/// Get the file name of the `Body`, if it's set.
432+
pub fn file_name(&self) -> Option<&str> {
433+
self.file_name.as_deref()
434+
}
435+
436+
/// Set the file name of the `Body`.
437+
pub fn set_file_name<S>(&mut self, file_name: Option<S>)
438+
where
439+
S: AsRef<str>,
440+
{
441+
self.file_name = file_name.map(|v| v.as_ref().to_owned());
442+
}
422443
}
423444

424445
impl Debug for Body {

src/lib.rs

+4
Original file line numberDiff line numberDiff line change
@@ -131,6 +131,10 @@ pub mod trace;
131131
pub mod transfer;
132132
pub mod upgrade;
133133

134+
cfg_unstable! {
135+
pub mod multipart;
136+
}
137+
134138
mod body;
135139
mod error;
136140
mod extensions;

src/multipart/entry.rs

+151
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,151 @@
1+
use crate::{Body, Mime};
2+
3+
use std::fmt::{self, Debug};
4+
// use std::path::Path;
5+
use std::pin::Pin;
6+
use std::task::{Context, Poll};
7+
8+
use futures_lite::{io, prelude::*};
9+
10+
pin_project_lite::pin_project! {
11+
/// A single multipart entry.
12+
///
13+
/// Structurally Multipart entries are similar to `Body`.
14+
pub struct Entry {
15+
name: String,
16+
body: Body,
17+
}
18+
}
19+
20+
impl Entry {
21+
/// Create a new `Entry`.
22+
pub fn new<S, B>(name: S, body: B) -> Self
23+
where
24+
S: AsRef<str>,
25+
B: Into<Body>,
26+
{
27+
Self {
28+
name: name.as_ref().to_owned(),
29+
body: body.into(),
30+
}
31+
}
32+
33+
/// Create an empty `Entry`.
34+
pub fn empty<S>(name: S) -> Self
35+
where
36+
S: AsRef<str>,
37+
{
38+
Self::new(name, Body::empty())
39+
}
40+
41+
/// Create an `Entry` from a file.
42+
#[cfg(all(feature = "async_std", not(target_os = "unknown")))]
43+
pub async fn from_file<S, P>(name: S, path: P) -> crate::Result<Self>
44+
where
45+
S: AsRef<str>,
46+
P: AsRef<Path>,
47+
{
48+
let body = Body::from_file(path).await?;
49+
Ok(Self::new(name, body))
50+
}
51+
52+
/// Get the entry name.
53+
pub fn name(&self) -> &String {
54+
&self.name
55+
}
56+
57+
/// Set the entry name.
58+
pub fn set_name<S>(&mut self, name: S)
59+
where
60+
S: AsRef<str>,
61+
{
62+
self.name = name.as_ref().to_owned();
63+
}
64+
65+
/// Returns the mime type of this Body.
66+
pub fn mime(&self) -> &Mime {
67+
self.body.mime()
68+
}
69+
70+
/// Sets the mime type of this Body.
71+
pub fn set_mime(&mut self, mime: Mime) {
72+
self.body.set_mime(mime)
73+
}
74+
75+
/// Get the file name of the entry, if it's set.
76+
pub fn file_name(&self) -> Option<&str> {
77+
self.body.file_name()
78+
}
79+
80+
/// Set the file name of the `Body`.
81+
pub fn set_file_name<P>(&mut self, file_name: Option<P>)
82+
where
83+
P: AsRef<str>,
84+
{
85+
self.body.set_file_name(file_name);
86+
}
87+
}
88+
89+
impl Debug for Entry {
90+
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
91+
f.debug_struct("Entry")
92+
.field("name", &self.name)
93+
.field("body", &self.body)
94+
.finish()
95+
}
96+
}
97+
98+
impl AsyncRead for Entry {
99+
#[allow(missing_doc_code_examples)]
100+
fn poll_read(
101+
mut self: Pin<&mut Self>,
102+
cx: &mut Context<'_>,
103+
buf: &mut [u8],
104+
) -> Poll<io::Result<usize>> {
105+
Pin::new(&mut self.body).poll_read(cx, buf)
106+
}
107+
}
108+
109+
impl AsyncBufRead for Entry {
110+
#[allow(missing_doc_code_examples)]
111+
#[allow(unused_mut)]
112+
#[allow(unused_variables)]
113+
fn poll_fill_buf(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<io::Result<&[u8]>> {
114+
// Pin::new(&mut self.body).poll_fill_buf(cx)
115+
todo!("Pin::new(&mut self.body).poll_fill_buf(cx)")
116+
}
117+
118+
fn consume(mut self: Pin<&mut Self>, amt: usize) {
119+
Pin::new(&mut self.body).consume(amt)
120+
}
121+
}
122+
123+
impl AsRef<Body> for Entry {
124+
fn as_ref(&self) -> &Body {
125+
&self.body
126+
}
127+
}
128+
129+
impl AsMut<Body> for Entry {
130+
fn as_mut(&mut self) -> &mut Body {
131+
&mut self.body
132+
}
133+
}
134+
135+
impl Into<Body> for Entry {
136+
fn into(self) -> Body {
137+
self.body
138+
}
139+
}
140+
141+
impl From<Body> for Entry {
142+
fn from(body: Body) -> Self {
143+
match body.file_name.clone() {
144+
Some(name) => Self { body, name },
145+
None => Self {
146+
body,
147+
name: String::new(),
148+
},
149+
}
150+
}
151+
}

0 commit comments

Comments
 (0)