@@ -19,96 +19,136 @@ macro_rules! get_build_var {
1919 } } ;
2020}
2121
22- /// Copy data from a vectored src to dest
22+ /// A reader to read a vector of byte slices
2323///
24- /// Copies `dest.len()` bytes from payload to dest,
25- /// starting after `offset` bytes.
26- ///
27- /// ## Panics
28- ///
29- /// This function will panic when not enough bytes are available to fill dest.
30- /// Total size of `payload` has to be `atleast dest.len()` + `offset`.
31- pub fn copy_vectored ( src : & [ & [ u8 ] ] , offset : usize , dest : & mut [ u8 ] ) {
32- let mut i = 0 ;
24+ #[ derive( Debug ) ]
25+ pub struct VectorReader {
26+ /// The index of the current slice
27+ ///
28+ /// Set to `vector.len()` when exhausted.
29+ slice_index : usize ,
30+ /// The index in the current slice
31+ ///
32+ /// E.g. the element to be read next.
33+ current_slice_offset : usize ,
34+ }
3335
34- while i < dest. len ( ) {
35- let payload_index = i + offset;
36- let next = get_sub_slice ( src, payload_index) ;
37- let remaining = dest. len ( ) - i;
38- if remaining > next. len ( ) {
39- dest[ i..( i + next. len ( ) ) ] . copy_from_slice ( next) ;
40- i += next. len ( ) ;
41- } else {
42- dest[ i..] . copy_from_slice ( & next[ ..remaining] ) ;
43- return ;
36+ impl VectorReader {
37+ /// Create a new reader
38+ pub fn new ( ) -> Self {
39+ VectorReader {
40+ slice_index : 0 ,
41+ current_slice_offset : 0 ,
4442 }
4543 }
46- }
44+ /// Read `dest.len()` bytes from `src` into `dest`, returning how many bytes were read
45+ ///
46+ /// Returns a [VectorReaderError] when the current position is out of range for `src`.
47+ ///
48+ /// The same `src` buffer has to be passed to subsequent calls to `read()`.
49+ /// Changing the vector is undefined behaviour.
50+ pub fn read (
51+ & mut self ,
52+ src : & [ & [ u8 ] ] ,
53+ dest : & mut [ u8 ] ,
54+ ) -> Result < usize , VectorReaderError > {
55+ let mut i = 0 ;
56+ while i < dest. len ( ) {
57+ if self . is_exhausted ( src) ? {
58+ return Ok ( i) ;
59+ }
4760
48- /// Get a slice of `vector` indexed by `offset`
49- ///
50- /// The `offset` is the absolute byte index.
51- /// The returned slice is the remaining sub slice starting at `offset`.
52- ///
53- /// ## Panics
54- ///
55- /// Will panic when offset is larger than the size of `vector`.
56- ///
57- /// ## Example
58- /// ```ignore
59- /// # use mctp_estack::fragment::get_slice;
60- /// let vector: &[&[u8]] = &[&[1, 2, 3], &[4, 5, 6]];
61- ///
62- /// let slice = get_slice(vector, 4);
63- ///
64- /// assert_eq!(slice, &[5, 6]);
65- /// ```
66- pub fn get_sub_slice < ' a > ( vector : & ' a [ & [ u8 ] ] , offset : usize ) -> & ' a [ u8 ] {
67- let mut i = offset;
68- for slice in vector {
69- if i >= slice. len ( ) {
70- i -= slice. len ( ) ;
71- } else {
72- return & slice[ i..] ;
61+ let slice = & src[ self . slice_index ] [ self . current_slice_offset ..] ;
62+ let n = slice. len ( ) . min ( dest[ i..] . len ( ) ) ;
63+ dest[ i..i + n] . copy_from_slice ( & slice[ ..n] ) ;
64+ i += n;
65+ self . increment_index ( src, n) ;
66+ }
67+ Ok ( i)
68+ }
69+ /// Checks if `src` has been read to the end
70+ ///
71+ /// Returns a [VectorReaderError] when the current position is out of range for `src`.
72+ ///
73+ /// _Note:_ Might return a `Ok` even if the `src` vector changed between calls.
74+ pub fn is_exhausted (
75+ & self ,
76+ src : & [ & [ u8 ] ] ,
77+ ) -> Result < bool , VectorReaderError > {
78+ if src. len ( ) == self . slice_index {
79+ return Ok ( true ) ;
80+ }
81+ // This shlould only occur if the caller passed varying vectors
82+ src. get ( self . slice_index ) . ok_or ( VectorReaderError ) ?;
83+ Ok ( false )
84+ }
85+ /// Increment the index by `n`, panic if out ouf bounds
86+ ///
87+ /// If this exhausts the vector exactly, the index is incremented to `vector[vector.len()][0]`
88+ fn increment_index ( & mut self , vector : & [ & [ u8 ] ] , n : usize ) {
89+ let mut n = n;
90+ loop {
91+ if vector[ self . slice_index ]
92+ . get ( self . current_slice_offset + n)
93+ . is_some ( )
94+ {
95+ // If we can index the current slice at offset + n just increment offset and return
96+ self . current_slice_offset += n;
97+ return ;
98+ } else {
99+ // Substract what has been read from the current slice, then increment to next slice
100+ n -=
101+ vector[ self . slice_index ] [ self . current_slice_offset ..] . len ( ) ;
102+ self . slice_index += 1 ;
103+ self . current_slice_offset = 0 ;
104+ if self . slice_index == vector. len ( ) {
105+ // return when the end of the vector is reached
106+ debug_assert_eq ! ( n, 0 ) ;
107+ return ;
108+ }
109+ }
73110 }
74111 }
75- panic ! ( "offset for vector out of bounds" ) ;
76112}
77113
114+ #[ derive( Debug ) ]
115+ pub struct VectorReaderError ;
116+
78117#[ cfg( test) ]
79118mod tests {
80119 #[ test]
81- fn test_get_slice ( ) {
82- use super :: get_sub_slice;
83- let vector: & [ & [ u8 ] ] = & [ & [ 1 , 2 , 3 ] , & [ 4 , 5 , 6 ] , & [ 7 , 8 , 9 ] ] ;
84- let slice = get_sub_slice ( vector, 4 ) ;
85- assert_eq ! ( slice, & [ 5 , 6 ] ) ;
86- let slice = get_sub_slice ( vector, 0 ) ;
87- assert_eq ! ( slice, & [ 1 , 2 , 3 ] ) ;
88- let slice = get_sub_slice ( vector, 3 ) ;
89- assert_eq ! ( slice, & [ 4 , 5 , 6 ] ) ;
90- }
91- #[ test]
92- fn test_copy_vectored ( ) {
93- use super :: copy_vectored;
120+ fn test_vector_reader ( ) {
121+ use super :: VectorReader ;
122+ let mut reader = VectorReader :: new ( ) ;
94123 let vector: & [ & [ u8 ] ] = & [ & [ 1 , 2 , 3 ] , & [ 4 , 5 ] , & [ 6 , 7 , 8 , 9 ] ] ;
95124
125+ // Test reading a vector partially
126+ let mut dest = [ 0 ; 4 ] ;
127+ let n = reader. read ( vector, & mut dest) . unwrap ( ) ;
128+ assert_eq ! ( n, 4 ) ;
129+ assert_eq ! ( & dest, & [ 1 , 2 , 3 , 4 ] ) ;
130+
131+ // Test reading all remaining elements into a larger than necessary destination
96132 let mut dest = [ 0 ; 6 ] ;
97- copy_vectored ( vector, 1 , & mut dest) ;
98- assert_eq ! ( & dest, & [ 2 , 3 , 4 , 5 , 6 , 7 ] ) ;
133+ let n = reader. read ( vector, & mut dest) . unwrap ( ) ;
134+ assert_eq ! ( n, 5 ) ;
135+ assert_eq ! ( & dest[ ..5 ] , & [ 5 , 6 , 7 , 8 , 9 ] ) ;
99136
100- let mut dest = [ 0 ; 5 ] ;
101- copy_vectored ( vector , 4 , & mut dest ) ;
102- assert_eq ! ( & dest , & [ 5 , 6 , 7 , 8 , 9 ] ) ;
137+ assert ! ( reader
138+ . is_exhausted ( vector )
139+ . expect ( "Vector should be exhausted" ) ) ;
103140
104- let mut dest = [ 0 ; 9 ] ;
105- copy_vectored ( vector , 0 , & mut dest ) ;
106- assert_eq ! ( & dest , & [ 1 , 2 , 3 , 4 , 5 , 6 , 7 , 8 , 9 ] ) ;
141+ // Test reading to end in one pass
142+ let mut reader = VectorReader :: new ( ) ;
143+ let vector : & [ & [ u8 ] ] = & [ & [ 1 , 2 , 3 ] , & [ 4 ] ] ;
107144
108- let vector: & [ & [ u8 ] ] = & [ & [ 1 , 2 , 3 ] ] ;
145+ let mut dest = [ 0 ; 4 ] ;
146+ let n = reader. read ( vector, & mut dest) . unwrap ( ) ;
147+ assert_eq ! ( n, 4 ) ;
148+ assert_eq ! ( & dest, & [ 1 , 2 , 3 , 4 ] ) ;
109149
110- let mut dest = [ 0 ; 1 ] ;
111- copy_vectored ( vector , 2 , & mut dest ) ;
112- assert_eq ! ( & dest , & [ 3 ] ) ;
150+ assert ! ( reader
151+ . is_exhausted ( vector )
152+ . expect ( "Vector should be exhausted" ) ) ;
113153 }
114154}
0 commit comments