1 use std::collections::VecDeque; 2 use std::io::IoSlice; 3 4 use bytes::{Buf, BufMut, Bytes, BytesMut}; 5 6 pub(crate) struct BufList<T> { 7 bufs: VecDeque<T>, 8 } 9 10 impl<T: Buf> BufList<T> { new() -> BufList<T>11 pub(crate) fn new() -> BufList<T> { 12 BufList { 13 bufs: VecDeque::new(), 14 } 15 } 16 17 #[inline] push(&mut self, buf: T)18 pub(crate) fn push(&mut self, buf: T) { 19 debug_assert!(buf.has_remaining()); 20 self.bufs.push_back(buf); 21 } 22 23 #[inline] 24 #[cfg(feature = "http1")] bufs_cnt(&self) -> usize25 pub(crate) fn bufs_cnt(&self) -> usize { 26 self.bufs.len() 27 } 28 } 29 30 impl<T: Buf> Buf for BufList<T> { 31 #[inline] remaining(&self) -> usize32 fn remaining(&self) -> usize { 33 self.bufs.iter().map(|buf| buf.remaining()).sum() 34 } 35 36 #[inline] chunk(&self) -> &[u8]37 fn chunk(&self) -> &[u8] { 38 self.bufs.front().map(Buf::chunk).unwrap_or_default() 39 } 40 41 #[inline] advance(&mut self, mut cnt: usize)42 fn advance(&mut self, mut cnt: usize) { 43 while cnt > 0 { 44 { 45 let front = &mut self.bufs[0]; 46 let rem = front.remaining(); 47 if rem > cnt { 48 front.advance(cnt); 49 return; 50 } else { 51 front.advance(rem); 52 cnt -= rem; 53 } 54 } 55 self.bufs.pop_front(); 56 } 57 } 58 59 #[inline] chunks_vectored<'t>(&'t self, dst: &mut [IoSlice<'t>]) -> usize60 fn chunks_vectored<'t>(&'t self, dst: &mut [IoSlice<'t>]) -> usize { 61 if dst.is_empty() { 62 return 0; 63 } 64 let mut vecs = 0; 65 for buf in &self.bufs { 66 vecs += buf.chunks_vectored(&mut dst[vecs..]); 67 if vecs == dst.len() { 68 break; 69 } 70 } 71 vecs 72 } 73 74 #[inline] copy_to_bytes(&mut self, len: usize) -> Bytes75 fn copy_to_bytes(&mut self, len: usize) -> Bytes { 76 // Our inner buffer may have an optimized version of copy_to_bytes, and if the whole 77 // request can be fulfilled by the front buffer, we can take advantage. 78 match self.bufs.front_mut() { 79 Some(front) if front.remaining() == len => { 80 let b = front.copy_to_bytes(len); 81 self.bufs.pop_front(); 82 b 83 } 84 Some(front) if front.remaining() > len => front.copy_to_bytes(len), 85 _ => { 86 assert!(len <= self.remaining(), "`len` greater than remaining"); 87 let mut bm = BytesMut::with_capacity(len); 88 bm.put(self.take(len)); 89 bm.freeze() 90 } 91 } 92 } 93 } 94 95 #[cfg(test)] 96 mod tests { 97 use std::ptr; 98 99 use super::*; 100 hello_world_buf() -> BufList<Bytes>101 fn hello_world_buf() -> BufList<Bytes> { 102 BufList { 103 bufs: vec![Bytes::from("Hello"), Bytes::from(" "), Bytes::from("World")].into(), 104 } 105 } 106 107 #[test] to_bytes_shorter()108 fn to_bytes_shorter() { 109 let mut bufs = hello_world_buf(); 110 let old_ptr = bufs.chunk().as_ptr(); 111 let start = bufs.copy_to_bytes(4); 112 assert_eq!(start, "Hell"); 113 assert!(ptr::eq(old_ptr, start.as_ptr())); 114 assert_eq!(bufs.chunk(), b"o"); 115 assert!(ptr::eq(old_ptr.wrapping_add(4), bufs.chunk().as_ptr())); 116 assert_eq!(bufs.remaining(), 7); 117 } 118 119 #[test] to_bytes_eq()120 fn to_bytes_eq() { 121 let mut bufs = hello_world_buf(); 122 let old_ptr = bufs.chunk().as_ptr(); 123 let start = bufs.copy_to_bytes(5); 124 assert_eq!(start, "Hello"); 125 assert!(ptr::eq(old_ptr, start.as_ptr())); 126 assert_eq!(bufs.chunk(), b" "); 127 assert_eq!(bufs.remaining(), 6); 128 } 129 130 #[test] to_bytes_longer()131 fn to_bytes_longer() { 132 let mut bufs = hello_world_buf(); 133 let start = bufs.copy_to_bytes(7); 134 assert_eq!(start, "Hello W"); 135 assert_eq!(bufs.remaining(), 4); 136 } 137 138 #[test] one_long_buf_to_bytes()139 fn one_long_buf_to_bytes() { 140 let mut buf = BufList::new(); 141 buf.push(b"Hello World" as &[_]); 142 assert_eq!(buf.copy_to_bytes(5), "Hello"); 143 assert_eq!(buf.chunk(), b" World"); 144 } 145 146 #[test] 147 #[should_panic(expected = "`len` greater than remaining")] buf_to_bytes_too_many()148 fn buf_to_bytes_too_many() { 149 hello_world_buf().copy_to_bytes(42); 150 } 151 } 152