@@ -942,6 +942,62 @@ impl<'a> IoSliceMut<'a> {
942942 pub fn new ( buf : & ' a mut [ u8 ] ) -> IoSliceMut < ' a > {
943943 IoSliceMut ( sys:: io:: IoSliceMut :: new ( buf) )
944944 }
945+
946+ /// Advance the internal cursor of the slice.
947+ ///
948+ /// # Notes
949+ ///
950+ /// Elements in the slice may be modified if the cursor is not advanced to
951+ /// the end of the slice. For example if we have a slice of buffers with 2
952+ /// `IoSliceMut`s, both of length 8, and we advance the cursor by 10 bytes
953+ /// the first `IoSliceMut` will be untouched however the second will be
954+ /// modified to remove the first 2 bytes (10 - 8).
955+ ///
956+ /// # Examples
957+ ///
958+ /// ```
959+ /// #![feature(io_slice_advance)]
960+ ///
961+ /// use std::io::IoSliceMut;
962+ /// use std::mem;
963+ /// use std::ops::Deref;
964+ ///
965+ /// let mut buf1 = [1; 8];
966+ /// let mut buf2 = [2; 16];
967+ /// let mut buf3 = [3; 8];
968+ /// let mut bufs = &mut [
969+ /// IoSliceMut::new(&mut buf1),
970+ /// IoSliceMut::new(&mut buf2),
971+ /// IoSliceMut::new(&mut buf3),
972+ /// ][..];
973+ ///
974+ /// // Mark 10 bytes as read.
975+ /// bufs = IoSliceMut::advance(mem::replace(&mut bufs, &mut []), 10);
976+ /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
977+ /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
978+ /// ```
979+ #[ unstable( feature = "io_slice_advance" , issue = "62726" ) ]
980+ #[ inline]
981+ pub fn advance < ' b > ( bufs : & ' b mut [ IoSliceMut < ' a > ] , n : usize ) -> & ' b mut [ IoSliceMut < ' a > ] {
982+ // Number of buffers to remove.
983+ let mut remove = 0 ;
984+ // Total length of all the to be removed buffers.
985+ let mut accumulated_len = 0 ;
986+ for buf in bufs. iter ( ) {
987+ if accumulated_len + buf. len ( ) > n {
988+ break ;
989+ } else {
990+ accumulated_len += buf. len ( ) ;
991+ remove += 1 ;
992+ }
993+ }
994+
995+ let bufs = & mut bufs[ remove..] ;
996+ if !bufs. is_empty ( ) {
997+ bufs[ 0 ] . 0 . advance ( n - accumulated_len)
998+ }
999+ bufs
1000+ }
9451001}
9461002
9471003#[ stable( feature = "iovec" , since = "1.36.0" ) ]
@@ -989,6 +1045,61 @@ impl<'a> IoSlice<'a> {
9891045 pub fn new ( buf : & ' a [ u8 ] ) -> IoSlice < ' a > {
9901046 IoSlice ( sys:: io:: IoSlice :: new ( buf) )
9911047 }
1048+
1049+ /// Advance the internal cursor of the slice.
1050+ ///
1051+ /// # Notes
1052+ ///
1053+ /// Elements in the slice may be modified if the cursor is not advanced to
1054+ /// the end of the slice. For example if we have a slice of buffers with 2
1055+ /// `IoSlice`s, both of length 8, and we advance the cursor by 10 bytes the
1056+ /// first `IoSlice` will be untouched however the second will be modified to
1057+ /// remove the first 2 bytes (10 - 8).
1058+ ///
1059+ /// # Examples
1060+ ///
1061+ /// ```
1062+ /// #![feature(io_slice_advance)]
1063+ ///
1064+ /// use std::io::IoSlice;
1065+ /// use std::mem;
1066+ /// use std::ops::Deref;
1067+ ///
1068+ /// let mut buf1 = [1; 8];
1069+ /// let mut buf2 = [2; 16];
1070+ /// let mut buf3 = [3; 8];
1071+ /// let mut bufs = &mut [
1072+ /// IoSlice::new(&mut buf1),
1073+ /// IoSlice::new(&mut buf2),
1074+ /// IoSlice::new(&mut buf3),
1075+ /// ][..];
1076+ ///
1077+ /// // Mark 10 bytes as written.
1078+ /// bufs = IoSlice::advance(mem::replace(&mut bufs, &mut []), 10);
1079+ /// assert_eq!(bufs[0].deref(), [2; 14].as_ref());
1080+ /// assert_eq!(bufs[1].deref(), [3; 8].as_ref());
1081+ #[ unstable( feature = "io_slice_advance" , issue = "62726" ) ]
1082+ #[ inline]
1083+ pub fn advance < ' b > ( bufs : & ' b mut [ IoSlice < ' a > ] , n : usize ) -> & ' b mut [ IoSlice < ' a > ] {
1084+ // Number of buffers to remove.
1085+ let mut remove = 0 ;
1086+ // Total length of all the to be removed buffers.
1087+ let mut accumulated_len = 0 ;
1088+ for buf in bufs. iter ( ) {
1089+ if accumulated_len + buf. len ( ) > n {
1090+ break ;
1091+ } else {
1092+ accumulated_len += buf. len ( ) ;
1093+ remove += 1 ;
1094+ }
1095+ }
1096+
1097+ let bufs = & mut bufs[ remove..] ;
1098+ if !bufs. is_empty ( ) {
1099+ bufs[ 0 ] . 0 . advance ( n - accumulated_len)
1100+ }
1101+ bufs
1102+ }
9921103}
9931104
9941105#[ stable( feature = "iovec" , since = "1.36.0" ) ]
@@ -2268,8 +2379,10 @@ impl<B: BufRead> Iterator for Lines<B> {
22682379#[ cfg( test) ]
22692380mod tests {
22702381 use crate :: io:: prelude:: * ;
2271- use crate :: io;
22722382 use super :: { Cursor , SeekFrom , repeat} ;
2383+ use crate :: io:: { self , IoSlice , IoSliceMut } ;
2384+ use crate :: mem;
2385+ use crate :: ops:: Deref ;
22732386
22742387 #[ test]
22752388 #[ cfg_attr( target_os = "emscripten" , ignore) ]
@@ -2537,4 +2650,89 @@ mod tests {
25372650
25382651 Ok ( ( ) )
25392652 }
2653+
2654+ #[ test]
2655+ fn io_slice_mut_advance ( ) {
2656+ let mut buf1 = [ 1 ; 8 ] ;
2657+ let mut buf2 = [ 2 ; 16 ] ;
2658+ let mut buf3 = [ 3 ; 8 ] ;
2659+ let mut bufs = & mut [
2660+ IoSliceMut :: new ( & mut buf1) ,
2661+ IoSliceMut :: new ( & mut buf2) ,
2662+ IoSliceMut :: new ( & mut buf3) ,
2663+ ] [ ..] ;
2664+
2665+ // Only in a single buffer..
2666+ bufs = IoSliceMut :: advance ( mem:: replace ( & mut bufs, & mut [ ] ) , 1 ) ;
2667+ assert_eq ! ( bufs[ 0 ] . deref( ) , [ 1 ; 7 ] . as_ref( ) ) ;
2668+ assert_eq ! ( bufs[ 1 ] . deref( ) , [ 2 ; 16 ] . as_ref( ) ) ;
2669+ assert_eq ! ( bufs[ 2 ] . deref( ) , [ 3 ; 8 ] . as_ref( ) ) ;
2670+
2671+ // Removing a buffer, leaving others as is.
2672+ bufs = IoSliceMut :: advance ( mem:: replace ( & mut bufs, & mut [ ] ) , 7 ) ;
2673+ assert_eq ! ( bufs[ 0 ] . deref( ) , [ 2 ; 16 ] . as_ref( ) ) ;
2674+ assert_eq ! ( bufs[ 1 ] . deref( ) , [ 3 ; 8 ] . as_ref( ) ) ;
2675+
2676+ // Removing a buffer and removing from the next buffer.
2677+ bufs = IoSliceMut :: advance ( mem:: replace ( & mut bufs, & mut [ ] ) , 18 ) ;
2678+ assert_eq ! ( bufs[ 0 ] . deref( ) , [ 3 ; 6 ] . as_ref( ) ) ;
2679+ }
2680+
2681+ #[ test]
2682+ fn io_slice_mut_advance_empty_slice ( ) {
2683+ let mut empty_bufs = & mut [ ] [ ..] ;
2684+ // Shouldn't panic.
2685+ IoSliceMut :: advance ( & mut empty_bufs, 1 ) ;
2686+ }
2687+
2688+ #[ test]
2689+ fn io_slice_mut_advance_beyond_total_length ( ) {
2690+ let mut buf1 = [ 1 ; 8 ] ;
2691+ let mut bufs = & mut [ IoSliceMut :: new ( & mut buf1) ] [ ..] ;
2692+
2693+ // Going beyond the total length should be ok.
2694+ bufs = IoSliceMut :: advance ( mem:: replace ( & mut bufs, & mut [ ] ) , 9 ) ;
2695+ assert ! ( bufs. is_empty( ) ) ;
2696+ }
2697+
2698+ #[ test]
2699+ fn io_slice_advance ( ) {
2700+ let mut buf1 = [ 1 ; 8 ] ;
2701+ let mut buf2 = [ 2 ; 16 ] ;
2702+ let mut buf3 = [ 3 ; 8 ] ;
2703+ let mut bufs =
2704+ & mut [ IoSlice :: new ( & mut buf1) , IoSlice :: new ( & mut buf2) , IoSlice :: new ( & mut buf3) ] [ ..] ;
2705+
2706+ // Only in a single buffer..
2707+ bufs = IoSlice :: advance ( mem:: replace ( & mut bufs, & mut [ ] ) , 1 ) ;
2708+ assert_eq ! ( bufs[ 0 ] . deref( ) , [ 1 ; 7 ] . as_ref( ) ) ;
2709+ assert_eq ! ( bufs[ 1 ] . deref( ) , [ 2 ; 16 ] . as_ref( ) ) ;
2710+ assert_eq ! ( bufs[ 2 ] . deref( ) , [ 3 ; 8 ] . as_ref( ) ) ;
2711+
2712+ // Removing a buffer, leaving others as is.
2713+ bufs = IoSlice :: advance ( mem:: replace ( & mut bufs, & mut [ ] ) , 7 ) ;
2714+ assert_eq ! ( bufs[ 0 ] . deref( ) , [ 2 ; 16 ] . as_ref( ) ) ;
2715+ assert_eq ! ( bufs[ 1 ] . deref( ) , [ 3 ; 8 ] . as_ref( ) ) ;
2716+
2717+ // Removing a buffer and removing from the next buffer.
2718+ bufs = IoSlice :: advance ( mem:: replace ( & mut bufs, & mut [ ] ) , 18 ) ;
2719+ assert_eq ! ( bufs[ 0 ] . deref( ) , [ 3 ; 6 ] . as_ref( ) ) ;
2720+ }
2721+
2722+ #[ test]
2723+ fn io_slice_advance_empty_slice ( ) {
2724+ let mut empty_bufs = & mut [ ] [ ..] ;
2725+ // Shouldn't panic.
2726+ IoSlice :: advance ( & mut empty_bufs, 1 ) ;
2727+ }
2728+
2729+ #[ test]
2730+ fn io_slice_advance_beyond_total_length ( ) {
2731+ let mut buf1 = [ 1 ; 8 ] ;
2732+ let mut bufs = & mut [ IoSlice :: new ( & mut buf1) ] [ ..] ;
2733+
2734+ // Going beyond the total length should be ok.
2735+ bufs = IoSlice :: advance ( mem:: replace ( & mut bufs, & mut [ ] ) , 9 ) ;
2736+ assert ! ( bufs. is_empty( ) ) ;
2737+ }
25402738}
0 commit comments