1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109
use std::mem; /// A type that represents an object that consumes a memory slice on demand. /// The consumer lives as long as the slice is alive. pub struct ByteConsumer<'b> { /// The memory slice that get's consumed. buffer: &'b [u8], } impl<'b> ByteConsumer<'b> { /// Creates a new ByteConsumer from a stream of bytes. pub fn new(stream: &'b [u8]) -> ByteConsumer { ByteConsumer { buffer: stream } } /// Consumes `nr_bytes` from the original slice and returns an `Option` that holds a reference /// to a memory slice which is `nr_bytes` long. If `nr_bytes` is greater than the remaining /// bytes of the consumer's slice then `None` is returned. /// /// # Arguments /// /// * `nr_bytes` - A number representing the number of bytes to consume /// /// *Note*: The memory slice returned is not copied, it's a reference to the initial slice /// /// # Examples /// /// ``` /// let mut consumer = ByteConsumer::new(&[10, 20, 30, 40]); /// let first_two = consumer.consume(2); /// let second_two = consumer.consume(2); /// /// assert!(first_two.is_some()); /// assert_eq!(first_two.unwrap(), [10, 20]); /// /// assert!(second_two.is_some()); /// assert_eq!(second_two.unwrap(), [30, 40]); /// /// assert_eq!(consumer.consume(1), None); /// ``` /// #[inline] pub fn consume(&mut self, nr_bytes: usize) -> Option<&'b [u8]> { if nr_bytes > self.buffer.len() || nr_bytes == 0 { None } else { let (res, remaining) = self.buffer.split_at(nr_bytes); self.buffer = remaining; Some(res) } } /// Consumes `nr_bytes` from the original slice and returns a reference to a memory slice which is `nr_bytes` long. /// /// # Arguments /// /// * `nr_bytes` - A number representing the number of bytes to consume /// /// # Panics /// /// If `nr_bytes` is greater than the remaining bytes in the consumer's slice then /// then it panics with a custom message. /// /// *Note*: The memory slice returned is not copied, it's a reference to the initial slice /// /// # Examples /// /// ``` /// let mut consumer = ByteConsumer::new(&[10, 20, 30, 40]); /// let first_two = consumer.consume_unchecked(2); /// let second_two = consumer.consume_unchecked(2); /// /// assert_eq!(first_two, [10, 20]); /// assert_eq!(second_two, [30, 40]); /// /// // let _next = consumer.consume_unchecked(1) <-- This should panic. /// ``` #[inline] pub fn consume_unchecked(&mut self, nr_bytes: usize) -> &'b [u8] { self.consume(nr_bytes).expect(format!( "[ByteConsumer]: The number of bytes requested ({}) is greater that the number of bytes available ({}).", nr_bytes, self.buffer.len() ).as_str()) } #[inline] pub fn consume_as<T: Copy>(&mut self) -> Option<T> { let bytes = self.consume(mem::size_of::<T>()); match bytes { Some(bytes) => unsafe { Some(*(bytes.as_ptr() as *const T)) }, None => None, } } #[inline] pub fn consume_as_unchecked<T: Copy>(&mut self) -> T { self.consume_as::<T>().unwrap() } } #[cfg(test)] mod tests { #[test] fn it_works() { assert_eq!(2 + 2, 4); } }