@@ -28,8 +28,6 @@ pub trait FdWritable: Write + AsFd + AsRawFd {}
2828
2929impl < T > FdWritable for T where T : Write + AsFd + AsRawFd { }
3030
31- const BUF_SIZE : usize = 1024 * 16 ;
32-
3331/// Conversion from a `rustix::io::Errno` into our `Error` which implements `UError`.
3432impl From < rustix:: io:: Errno > for Error {
3533 fn from ( error : rustix:: io:: Errno ) -> Self {
5553{
5654 // If we're on Linux or Android, try to use the splice() system call
5755 // for faster writing. If it works, we're done.
58- if !splice_write ( src, & dest. as_fd ( ) ) ? {
56+ if !splice_write ( src, dest) ? {
5957 return Ok ( ( ) ) ;
6058 }
6159
@@ -78,17 +76,17 @@ where
7876/// - `source` - source handle
7977/// - `dest` - destination handle
8078#[ inline]
81- pub ( crate ) fn splice_write < R , S > ( source : & R , dest : & S ) -> UResult < bool >
79+ pub ( crate ) fn splice_write < R , S > ( source : & R , dest : & mut S ) -> UResult < bool >
8280where
8381 R : Read + AsFd + AsRawFd ,
84- S : AsRawFd + AsFd ,
82+ S : AsRawFd + AsFd + Write ,
8583{
86- let ( pipe_rd, pipe_wr) = pipe ( ) ?;
84+ let ( pipe_rd, pipe_wr) = pipe ( ) ?; // todo: bypass this if input or output is pipe. We use this mostly for stream.
8785 // improve throughput
8886 // no need to increase pipe size of input fd since
8987 // - sender with splice probably increased size already
9088 // - sender without splice is bottleneck
91- let _ = rustix:: pipe:: fcntl_setpipe_size ( dest, MAX_ROOTLESS_PIPE_SIZE ) ;
89+ let _ = rustix:: pipe:: fcntl_setpipe_size ( & mut * dest, MAX_ROOTLESS_PIPE_SIZE ) ;
9290
9391 loop {
9492 match splice ( & source, & pipe_wr, MAX_ROOTLESS_PIPE_SIZE ) {
@@ -100,36 +98,13 @@ where
10098 // we can recover by copying the data that we have from the
10199 // intermediate pipe to stdout using normal read/write. Then
102100 // we tell the caller to fall back.
103- copy_exact ( & pipe_rd, dest, n) ?;
101+ let mut drain = Vec :: with_capacity ( n) ; // bounded by pipe size
102+ pipe_rd. take ( n as u64 ) . read_to_end ( & mut drain) ?;
103+ dest. write_all ( & drain) ?;
104104 return Ok ( true ) ;
105105 }
106106 }
107107 Err ( _) => return Ok ( true ) ,
108108 }
109109 }
110110}
111-
112- /// Move exactly `num_bytes` bytes from `read_fd` to `write_fd` using the `read`
113- /// and `write` calls.
114- #[ cfg( any( target_os = "linux" , target_os = "android" ) ) ]
115- pub ( crate ) fn copy_exact (
116- read_fd : & impl AsFd ,
117- write_fd : & impl AsFd ,
118- num_bytes : usize ,
119- ) -> std:: io:: Result < usize > {
120- let mut left = num_bytes;
121- let mut buf = [ 0 ; BUF_SIZE ] ;
122- let mut total_written = 0 ;
123- while left > 0 {
124- let n_read = rustix:: io:: read ( read_fd, & mut buf) ?;
125- assert_ne ! ( n_read, 0 , "unexpected end of pipe" ) ;
126- let mut written = 0 ;
127- while written < n_read {
128- let n = rustix:: io:: write ( write_fd, & buf[ written..n_read] ) ?;
129- written += n;
130- }
131- total_written += written;
132- left -= n_read;
133- }
134- Ok ( total_written)
135- }
0 commit comments