Expose DataStream directly to allow for stream composition.

This commit is contained in:
Sergio Benitez 2017-01-05 15:13:13 -06:00
parent 069f09cb7e
commit 042dcadf43
4 changed files with 68 additions and 19 deletions

View File

@ -1,4 +1,4 @@
use std::io::{self, BufRead, Read, Write, Cursor, BufReader};
use std::io::{self, Read, Write, Cursor, BufReader};
use std::path::Path;
use std::fs::File;
use std::time::Duration;
@ -61,7 +61,7 @@ impl Data {
/// including that in the `peek` buffer. The method consumes the `Data`
/// instance. This ensures that a `Data` type _always_ represents _all_ of
/// the data in a request.
pub fn open(mut self) -> impl BufRead {
pub fn open(mut self) -> DataStream {
// Swap out the buffer and stream for empty ones so we can move.
let mut buffer = vec![];
let mut stream = EmptyReader(self.stream.get_ref().clone());
@ -71,13 +71,15 @@ impl Data {
// Setup the underlying reader at the correct pointers.
let mut cursor = Cursor::new(buffer);
cursor.set_position(self.position as u64);
let buffered = cursor.take((self.capacity - self.position) as u64);
// Create the actual DataSteam.
DataStream {
network: stream.get_ref().clone(),
stream: buffered.chain(BufReader::new(stream)),
}
// Get a reference to the underlying network stream.
let network = stream.get_ref().clone();
// The first part of the stream is the buffer. Then the real steam.
let buf = cursor.take((self.capacity - self.position) as u64);
let stream = buf.chain(BufReader::new(stream));
DataStream::new(stream, network)
}
#[doc(hidden)]

View File

@ -7,9 +7,22 @@ use http::hyper::h1::HttpReader;
pub type StreamReader = HttpReader<HttpStream>;
pub type InnerStream = Chain<Take<Cursor<Vec<u8>>>, BufReader<StreamReader>>;
/// Raw data stream of a request body.
///
/// This stream can only be obtained by calling
/// [Data::open](/rocket/data/struct.Data.html#method.open). The stream contains
/// all of the data in the body of the request. It exposes no methods directly.
/// Instead, it must be used as an opaque `Read` or `BufRead` structure.
pub struct DataStream {
pub stream: InnerStream,
pub network: HttpStream,
stream: InnerStream,
network: HttpStream,
}
impl DataStream {
#[doc(hidden)]
pub fn new(stream: InnerStream, network: HttpStream) -> DataStream {
DataStream { stream: stream, network: network, }
}
}
impl Read for DataStream {

View File

@ -1,11 +1,25 @@
//! Types and traits for reading and parsing request body data.
#[cfg(any(test, feature = "testing"))] mod test_data;
#[cfg(not(any(test, feature = "testing")))] mod data;
#[cfg(not(any(test, feature = "testing")))] mod data_stream;
#[cfg(any(test, feature = "testing"))]
#[path = "."]
mod items {
mod test_data;
pub use self::test_data::Data;
pub use self::test_data::DataStream;
}
#[cfg(not(any(test, feature = "testing")))]
#[path = "."]
mod items {
mod data;
mod data_stream;
pub use self::data::Data;
pub use self::data_stream::DataStream;
}
mod from_data;
pub use self::from_data::{FromData, Outcome};
#[cfg(any(test, feature = "testing"))] pub use self::test_data::Data;
#[cfg(not(any(test, feature = "testing")))] pub use self::data::Data;
pub use self::items::{Data, DataStream};

View File

@ -1,4 +1,4 @@
use std::io::{self, BufRead, Write, Cursor, BufReader};
use std::io::{self, Read, BufRead, Write, Cursor, BufReader};
use std::path::Path;
use std::fs::File;
@ -11,13 +11,33 @@ pub type BodyReader<'a, 'b> =
const PEEK_BYTES: usize = 4096;
pub struct DataStream {
stream: BufReader<Cursor<Vec<u8>>>,
}
impl Read for DataStream {
fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
self.stream.read(buf)
}
}
impl BufRead for DataStream {
fn fill_buf(&mut self) -> io::Result<&[u8]> {
self.stream.fill_buf()
}
fn consume(&mut self, amt: usize) {
self.stream.consume(amt)
}
}
pub struct Data {
data: Vec<u8>,
}
impl Data {
pub fn open(self) -> impl BufRead {
BufReader::new(Cursor::new(self.data))
pub fn open(self) -> DataStream {
DataStream { stream: BufReader::new(Cursor::new(self.data)) }
}
#[inline(always)]