@@ -9,7 +9,7 @@ use pyo3::{IntoPyObjectExt, exceptions::PyStopIteration, prelude::*, types::PyBy
99use std:: {
1010 borrow:: Cow ,
1111 collections:: VecDeque ,
12- io:: { BufRead , Cursor } ,
12+ io:: { BufRead , Cursor , Read } ,
1313 mem,
1414 sync:: Mutex ,
1515} ;
@@ -64,12 +64,36 @@ impl MultiPartParser {
6464 where
6565 T : AsRef < [ u8 ] > ,
6666 {
67+ macro_rules! buffered_read {
68+ ( $boundary: expr, $target: expr) => { {
69+ let peeker = reader. fill_buf( ) ?;
70+ if peeker. is_empty( ) {
71+ return Ok ( ( ) ) ;
72+ }
73+ // if the chunk is not long enough to check for boundary, buffer
74+ if ( peeker. len( ) + self . buffer. len( ) ) < $boundary. len( ) {
75+ reader. read_to_end( & mut self . buffer) ?;
76+ return Ok ( ( ) ) ;
77+ }
78+
79+ if self . buffer. is_empty( ) {
80+ reader. stream_until_token( $boundary, $target) ?
81+ } else {
82+ // we buffered previous contents, chain the two reads
83+ let mut chain = self . buffer. chain( & mut * reader) ;
84+ let ret = chain. stream_until_token( $boundary, $target) ?;
85+ self . buffer. truncate( 0 ) ;
86+ ret
87+ }
88+ } } ;
89+ }
90+
6791 let ( lt, ltlt, lt_boundary) = & self . boundaries ;
6892
6993 loop {
70- let peeker = reader. fill_buf ( ) ?;
71-
7294 if let MultiPartParserState :: Clean = self . state {
95+ let peeker = reader. fill_buf ( ) ?;
96+
7397 // If the last chunk is empty and we're in clean state there's nothing to do.
7498 if peeker. is_empty ( ) {
7599 return Ok ( ( ) ) ;
@@ -122,6 +146,9 @@ impl MultiPartParser {
122146 } ?
123147 } ;
124148
149+ // clean the buffer
150+ self . buffer . truncate ( 0 ) ;
151+
125152 let mut is_file = false ;
126153 let mut missing_mime = false ;
127154 if let Some ( cd) = part_headers. get ( header:: CONTENT_DISPOSITION ) {
@@ -154,7 +181,7 @@ impl MultiPartParser {
154181 }
155182
156183 if let MultiPartParserState :: Value ( part) = & mut self . state {
157- let ( read, found) = reader . stream_until_token ( lt_boundary, & mut part. value ) ? ;
184+ let ( read, found) = buffered_read ! ( lt_boundary, & mut part. value) ;
158185 self . read_size += read;
159186 if self . read_size >= self . max_part_size {
160187 return Err ( error_size ! ( ) ) ;
@@ -175,11 +202,10 @@ impl MultiPartParser {
175202 }
176203
177204 if let MultiPartParserState :: File ( filepart) = & mut self . state {
178- // potentially allow py threads?
179- let ( read, found) = reader. stream_until_token (
205+ let ( read, found) = buffered_read ! (
180206 lt_boundary,
181- & mut filepart. file . as_mut ( ) . expect ( "uninitialized file part" ) ,
182- ) ? ;
207+ & mut filepart. file. as_mut( ) . expect( "uninitialized file part" )
208+ ) ;
183209 let size = filepart. size . unwrap_or ( 0 ) ;
184210 filepart. size = Some ( size + read) ;
185211
0 commit comments