refactor(http): allow MemSlice to be sliced to make copies
This commit is contained in:
		
							
								
								
									
										110
									
								
								src/http/buf.rs
									
									
									
									
									
								
							
							
						
						
									
										110
									
								
								src/http/buf.rs
									
									
									
									
									
								
							| @@ -1,6 +1,7 @@ | |||||||
| use std::cell::UnsafeCell; | use std::cell::UnsafeCell; | ||||||
| use std::fmt; | use std::fmt; | ||||||
| use std::io::{self, Read}; | use std::io::{self, Read}; | ||||||
|  | use std::ops::{Deref, Range, RangeFrom, RangeTo, RangeFull}; | ||||||
| use std::ptr; | use std::ptr; | ||||||
| use std::sync::Arc; | use std::sync::Arc; | ||||||
|  |  | ||||||
| @@ -189,9 +190,80 @@ impl MemSlice { | |||||||
|             end: 0, |             end: 0, | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
|  |     pub fn slice<S: Slice>(&self, range: S) -> MemSlice { | ||||||
|  |         range.slice(self) | ||||||
|  |     } | ||||||
| } | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | impl fmt::Debug for MemSlice { | ||||||
|  |     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { | ||||||
|  |         fmt::Debug::fmt(&**self, f) | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl Deref for  MemSlice { | ||||||
|  |     type Target = [u8]; | ||||||
|  |     fn deref(&self) -> &[u8] { | ||||||
|  |         unsafe { | ||||||
|  |             &(*self.buf.get())[self.start..self.end] | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | pub trait Slice { | ||||||
|  |     fn slice(self, subject: &MemSlice) -> MemSlice; | ||||||
|  | } | ||||||
|  |  | ||||||
|  |  | ||||||
|  | impl Slice for Range<usize> { | ||||||
|  |     fn slice(self, subject: &MemSlice) -> MemSlice { | ||||||
|  |         assert!(subject.start + self.start <= subject.end); | ||||||
|  |         assert!(subject.start + self.end <= subject.end); | ||||||
|  |         MemSlice { | ||||||
|  |             buf: subject.buf.clone(), | ||||||
|  |             start: subject.start + self.start, | ||||||
|  |             end: subject.start + self.end, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl Slice for RangeFrom<usize> { | ||||||
|  |     fn slice(self, subject: &MemSlice) -> MemSlice { | ||||||
|  |         assert!(subject.start + self.start <= subject.end); | ||||||
|  |         MemSlice { | ||||||
|  |             buf: subject.buf.clone(), | ||||||
|  |             start: subject.start + self.start, | ||||||
|  |             end: subject.end, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl Slice for RangeTo<usize> { | ||||||
|  |     fn slice(self, subject: &MemSlice) -> MemSlice { | ||||||
|  |         assert!(subject.start + self.end <= subject.end); | ||||||
|  |         MemSlice { | ||||||
|  |             buf: subject.buf.clone(), | ||||||
|  |             start: subject.start, | ||||||
|  |             end: subject.start + self.end, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | impl Slice for RangeFull { | ||||||
|  |     fn slice(self, subject: &MemSlice) -> MemSlice { | ||||||
|  |         MemSlice { | ||||||
|  |             buf: subject.buf.clone(), | ||||||
|  |             start: subject.start, | ||||||
|  |             end: subject.end, | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | } | ||||||
|  |  | ||||||
|  | unsafe impl Send for MemBuf {} | ||||||
|  | unsafe impl Send for MemSlice {} | ||||||
|  |  | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| impl<T: Read> ::http::io::MemRead for ::mock::AsyncIo<T> { | impl<T: Read> ::http::io::MemRead for ::mock::AsyncIo<T> { | ||||||
|     fn read_mem(&mut self, len: usize) -> io::Result<MemSlice> { |     fn read_mem(&mut self, len: usize) -> io::Result<MemSlice> { | ||||||
| @@ -206,30 +278,26 @@ impl<T: Read> ::http::io::MemRead for ::mock::AsyncIo<T> { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| impl fmt::Debug for MemSlice { |  | ||||||
|     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { |  | ||||||
|         fmt::Debug::fmt(&**self, f) |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| impl ::std::ops::Deref for  MemSlice { |  | ||||||
|     type Target = [u8]; |  | ||||||
|     fn deref(&self) -> &[u8] { |  | ||||||
|         unsafe { |  | ||||||
|             &(*self.buf.get())[self.start..self.end] |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
| } |  | ||||||
|  |  | ||||||
| unsafe impl Send for MemBuf {} |  | ||||||
| unsafe impl Send for MemSlice {} |  | ||||||
|  |  | ||||||
| /* |  | ||||||
| #[cfg(test)] | #[cfg(test)] | ||||||
| mod tests { | mod tests { | ||||||
|     use super::{MemBuf}; |     use super::{MemBuf}; | ||||||
|  |  | ||||||
|     #[test] |     #[test] | ||||||
|     fn test_ |     fn test_mem_slice_slice() { | ||||||
|  |         let mut buf = MemBuf::with_capacity(32); | ||||||
|  |         buf.read_from(&mut &b"Hello World"[..]).unwrap(); | ||||||
|  |  | ||||||
|  |         let len = buf.len(); | ||||||
|  |         let full = buf.slice(len); | ||||||
|  |  | ||||||
|  |         assert_eq!(&*full, b"Hello World"); | ||||||
|  |         assert_eq!(&*full.slice(6..), b"World"); | ||||||
|  |         assert_eq!(&*full.slice(..5), b"Hello"); | ||||||
|  |         assert_eq!(&*full.slice(..), b"Hello World"); | ||||||
|  |         for a in 0..len { | ||||||
|  |             for b in a..len { | ||||||
|  |                 assert_eq!(&*full.slice(a..b), &b"Hello World"[a..b], "{}..{}", a, b); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  |     } | ||||||
| } | } | ||||||
| */ |  | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user