@@ -6,6 +6,7 @@ use std::{
6
6
borrow:: Cow ,
7
7
cmp,
8
8
collections:: VecDeque ,
9
+ convert:: TryFrom ,
9
10
fmt,
10
11
io:: { Error , ErrorKind , SeekFrom } ,
11
12
marker,
@@ -16,7 +17,7 @@ use std::{
16
17
use tokio:: {
17
18
fs,
18
19
fs:: { remove_dir_all, remove_file, OpenOptions } ,
19
- io:: { self , AsyncRead as Read , AsyncReadExt , AsyncSeekExt } ,
20
+ io:: { self , AsyncRead as Read , AsyncReadExt , AsyncSeekExt , AsyncWriteExt } ,
20
21
} ;
21
22
22
23
/// A read-only view into an entry of an archive.
@@ -689,22 +690,29 @@ impl<R: Read + Unpin> EntryFields<R> {
689
690
}
690
691
}
691
692
} ?;
693
+
694
+ let size = usize:: try_from ( self . size ) . unwrap_or ( usize:: MAX ) ;
695
+ let capacity = cmp:: min ( size, 128 * 1024 ) ;
696
+ let mut writer = io:: BufWriter :: with_capacity ( capacity, & mut f) ;
692
697
for io in self . data . drain ( ..) {
693
698
match io {
694
699
EntryIo :: Data ( mut d) => {
695
700
let expected = d. limit ( ) ;
696
- if io:: copy ( & mut d, & mut f ) . await ? != expected {
701
+ if io:: copy ( & mut d, & mut writer ) . await ? != expected {
697
702
return Err ( other ( "failed to write entire file" ) ) ;
698
703
}
699
704
}
700
705
EntryIo :: Pad ( d) => {
701
706
// TODO: checked cast to i64
702
- let to = SeekFrom :: Current ( d. limit ( ) as i64 ) ;
703
- let size = f. seek ( to) . await ?;
704
- f. set_len ( size) . await ?;
707
+ let pad_len = d. limit ( ) as i64 ;
708
+ writer. flush ( ) . await ?;
709
+ let f = writer. get_mut ( ) ;
710
+ let new_size = f. seek ( SeekFrom :: Current ( pad_len) ) . await ?;
711
+ f. set_len ( new_size) . await ?;
705
712
}
706
713
}
707
714
}
715
+ writer. flush ( ) . await ?;
708
716
Ok :: < fs:: File , io:: Error > ( f)
709
717
}
710
718
. await
0 commit comments