1 use std::ops; 2 3 /// A owned window around an underlying buffer. 4 /// 5 /// Normally slices work great for considering sub-portions of a buffer, but 6 /// unfortunately a slice is a *borrowed* type in Rust which has an associated 7 /// lifetime. When working with future and async I/O these lifetimes are not 8 /// always appropriate, and are sometimes difficult to store in tasks. This 9 /// type strives to fill this gap by providing an "owned slice" around an 10 /// underlying buffer of bytes. 11 /// 12 /// A `Window<T>` wraps an underlying buffer, `T`, and has configurable 13 /// start/end indexes to alter the behavior of the `AsRef<[u8]>` implementation 14 /// that this type carries. 15 /// 16 /// This type can be particularly useful when working with the `write_all` 17 /// combinator in this crate. Data can be sliced via `Window`, consumed by 18 /// `write_all`, and then earned back once the write operation finishes through 19 /// the `into_inner` method on this type. 20 #[derive(Debug)] 21 pub struct Window<T> { 22 inner: T, 23 range: ops::Range<usize>, 24 } 25 26 impl<T: AsRef<[u8]>> Window<T> { 27 /// Creates a new window around the buffer `t` defaulting to the entire 28 /// slice. 29 /// 30 /// Further methods can be called on the returned `Window<T>` to alter the 31 /// window into the data provided. new(t: T) -> Window<T>32 pub fn new(t: T) -> Window<T> { 33 Window { 34 range: 0..t.as_ref().len(), 35 inner: t, 36 } 37 } 38 39 /// Gets a shared reference to the underlying buffer inside of this 40 /// `Window`. get_ref(&self) -> &T41 pub fn get_ref(&self) -> &T { 42 &self.inner 43 } 44 45 /// Gets a mutable reference to the underlying buffer inside of this 46 /// `Window`. get_mut(&mut self) -> &mut T47 pub fn get_mut(&mut self) -> &mut T { 48 &mut self.inner 49 } 50 51 /// Consumes this `Window`, returning the underlying buffer. into_inner(self) -> T52 pub fn into_inner(self) -> T { 53 self.inner 54 } 55 56 /// Returns the starting index of this window into the underlying buffer 57 /// `T`. start(&self) -> usize58 pub fn start(&self) -> usize { 59 self.range.start 60 } 61 62 /// Returns the end index of this window into the underlying buffer 63 /// `T`. end(&self) -> usize64 pub fn end(&self) -> usize { 65 self.range.end 66 } 67 68 /// Changes the starting index of this window to the index specified. 69 /// 70 /// Returns the windows back to chain multiple calls to this method. 71 /// 72 /// # Panics 73 /// 74 /// This method will panic if `start` is out of bounds for the underlying 75 /// slice or if it comes after the `end` configured in this window. set_start(&mut self, start: usize) -> &mut Window<T>76 pub fn set_start(&mut self, start: usize) -> &mut Window<T> { 77 assert!(start <= self.inner.as_ref().len()); 78 assert!(start <= self.range.end); 79 self.range.start = start; 80 self 81 } 82 83 /// Changes the end index of this window to the index specified. 84 /// 85 /// Returns the windows back to chain multiple calls to this method. 86 /// 87 /// # Panics 88 /// 89 /// This method will panic if `end` is out of bounds for the underlying 90 /// slice or if it comes before the `start` configured in this window. set_end(&mut self, end: usize) -> &mut Window<T>91 pub fn set_end(&mut self, end: usize) -> &mut Window<T> { 92 assert!(end <= self.inner.as_ref().len()); 93 assert!(self.range.start <= end); 94 self.range.end = end; 95 self 96 } 97 98 // TODO: how about a generic set() method along the lines of: 99 // 100 // buffer.set(..3) 101 // .set(0..2) 102 // .set(4..) 103 // 104 // etc. 105 } 106 107 impl<T: AsRef<[u8]>> AsRef<[u8]> for Window<T> { as_ref(&self) -> &[u8]108 fn as_ref(&self) -> &[u8] { 109 &self.inner.as_ref()[self.range.start..self.range.end] 110 } 111 } 112 113 impl<T: AsMut<[u8]>> AsMut<[u8]> for Window<T> { as_mut(&mut self) -> &mut [u8]114 fn as_mut(&mut self) -> &mut [u8] { 115 &mut self.inner.as_mut()[self.range.start..self.range.end] 116 } 117 } 118