diff --git a/actix-multipart-derive/src/lib.rs b/actix-multipart-derive/src/lib.rs index 04db36825..901d0c46a 100644 --- a/actix-multipart-derive/src/lib.rs +++ b/actix-multipart-derive/src/lib.rs @@ -76,21 +76,21 @@ pub fn derive(input: TokenStream) -> TokenStream { quote! { #ident: self.#ident.unwrap() } }); - let field_appending = fields.iter().map(|f| { + let bytes_appending = fields.iter().map(|f| { + let Field { ident, .. } = f; + + quote! { + stringify!(#ident) => field_bytes.put(chunk), + } + }); + + let fields_from_bytes = fields.iter().map(|f| { let Field { ident, ty, .. } = f; quote! { - stringify!(#ident) => match builder.#ident { - Some(ref mut field) => { - field.append(chunk); - } - None => { - let mut field = #ty::default(); - field.append(chunk); - builder.#ident.replace(field); - } - }, - + stringify!(#ident) => { + builder.#ident.replace(#ty::from_bytes(field_bytes)); + } } }); @@ -121,9 +121,11 @@ pub fn derive(input: TokenStream) -> TokenStream { type Config = (); fn from_request(req: &::actix_web::HttpRequest, payload: &mut ::actix_web::dev::Payload) -> Self::Future { - use futures_util::future::FutureExt; - use futures_util::stream::StreamExt; - use actix_multipart::BuildFromBytes; + use ::futures_util::future::FutureExt; + use ::futures_util::stream::StreamExt; + use ::actix_web::error; + use ::actix_multipart::{FromBytes, Multipart}; + use ::bytes::{BufMut, BytesMut}; let pl = payload.take(); let req2 = req.clone(); @@ -140,26 +142,36 @@ pub fn derive(input: TokenStream) -> TokenStream { let cd = field.content_disposition().unwrap(); let name = cd.get_name().unwrap(); - println!("FIELD: {}", name); let mut size = 0; + let mut field_bytes = BytesMut::new(); while let Some(chunk) = field.next().await { let chunk = chunk?; size += chunk.len(); if (size > #b_ident::max_size(&name).unwrap_or(std::usize::MAX)) { - return Err(::actix_web::error::ErrorPayloadTooLarge("field is too large")); + return Err(error::ErrorPayloadTooLarge("field is too large")); } match name { - #(#field_appending)* + #(#bytes_appending)* - _ => todo!("unknown field"), + _ => { + // unknown field + }, } } - println!(); + let field_bytes = field_bytes.freeze(); + + match name { + #(#fields_from_bytes)* + + _ => { + // unknown field + }, + } } builder.build() diff --git a/actix-multipart/src/byte_builder.rs b/actix-multipart/src/byte_builder.rs index 3377cf927..cb1f0619c 100644 --- a/actix-multipart/src/byte_builder.rs +++ b/actix-multipart/src/byte_builder.rs @@ -1,18 +1,25 @@ -use bytes::{BufMut, Bytes, BytesMut}; +use bytes::{Bytes, BytesMut}; -pub trait BuildFromBytes { - fn append(&mut self, next: Bytes); +pub trait FromBytes { + fn from_bytes(next: Bytes) -> Self; } -impl BuildFromBytes for String { - fn append(&mut self, chunk: Bytes) { - let chunk_str = std::str::from_utf8(&chunk).expect("string field is not utf-8"); - self.push_str(chunk_str); +impl FromBytes for String { + fn from_bytes(bytes: Bytes) -> Self { + std::str::from_utf8(&bytes) + .expect("string field is not utf-8") + .to_owned() } } -impl BuildFromBytes for BytesMut { - fn append(&mut self, chunk: Bytes) { - self.put(&chunk[..]); +impl FromBytes for Bytes { + fn from_bytes(bytes: Bytes) -> Self { + bytes + } +} + +impl FromBytes for BytesMut { + fn from_bytes(bytes: Bytes) -> Self { + BytesMut::from(bytes.as_ref()) } } diff --git a/actix-multipart/src/lib.rs b/actix-multipart/src/lib.rs index f67e57cb6..3e8d70fce 100644 --- a/actix-multipart/src/lib.rs +++ b/actix-multipart/src/lib.rs @@ -5,6 +5,6 @@ mod error; mod extractor; mod server; -pub use self::byte_builder::BuildFromBytes; +pub use self::byte_builder::FromBytes; pub use self::error::MultipartError; pub use self::server::{Field, Multipart};