@@ -942,6 +942,62 @@ impl<'a> IoSliceMut<'a> {
942
942
pub fn new ( buf : & ' a mut [ u8 ] ) -> IoSliceMut < ' a > {
943
943
IoSliceMut ( sys:: io:: IoSliceMut :: new ( buf) )
944
944
}
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
+ }
945
1001
}
946
1002
947
1003
#[ stable( feature = "iovec" , since = "1.36.0" ) ]
@@ -989,6 +1045,61 @@ impl<'a> IoSlice<'a> {
989
1045
pub fn new ( buf : & ' a [ u8 ] ) -> IoSlice < ' a > {
990
1046
IoSlice ( sys:: io:: IoSlice :: new ( buf) )
991
1047
}
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
+ }
992
1103
}
993
1104
994
1105
#[ stable( feature = "iovec" , since = "1.36.0" ) ]
@@ -2268,8 +2379,10 @@ impl<B: BufRead> Iterator for Lines<B> {
2268
2379
#[ cfg( test) ]
2269
2380
mod tests {
2270
2381
use crate :: io:: prelude:: * ;
2271
- use crate :: io;
2272
2382
use super :: { Cursor , SeekFrom , repeat} ;
2383
+ use crate :: io:: { self , IoSlice , IoSliceMut } ;
2384
+ use crate :: mem;
2385
+ use crate :: ops:: Deref ;
2273
2386
2274
2387
#[ test]
2275
2388
#[ cfg_attr( target_os = "emscripten" , ignore) ]
@@ -2537,4 +2650,89 @@ mod tests {
2537
2650
2538
2651
Ok ( ( ) )
2539
2652
}
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
+ }
2540
2738
}
0 commit comments