use futures::{Future, Stream, Async, Poll};
use futures::Async::*;
use mime::{self, Mime};
use std::rc::Rc;
use std::{io, mem, str};
use server::boundary::BoundaryFinder;
use server::{Internal, BodyChunk, StreamError, httparse};
use helpers::*;
use self::httparse::EMPTY_HEADER;
mod collect;
mod headers;
pub use self::headers::{FieldHeaders, ReadHeaders};
pub use self::collect::{ReadTextField, TextField};
pub(super) fn new_field<S: Stream>(headers: FieldHeaders, internal: Rc<Internal<S>>) -> Field<S> {
let headers = Rc::new(headers);
Field {
headers: headers.clone(),
data: FieldData {
headers, internal
},
_priv: (),
}
}
pub struct Field<S: Stream> {
pub headers: Rc<FieldHeaders>,
pub data: FieldData<S>,
_priv: (),
}
pub struct FieldData<S: Stream> {
headers: Rc<FieldHeaders>,
internal: Rc<Internal<S>>,
}
impl<S: Stream> FieldData<S> where S::Item: BodyChunk, S::Error: StreamError {
pub fn read_text(self) -> ReadTextField<S> {
if !self.headers.is_text() {
debug!("attempting to read a non-text field as text: {:?}", self.headers);
}
collect::read_text(self)
}
fn stream_mut(&mut self) -> &mut BoundaryFinder<S> {
debug_assert!(Rc::strong_count(&self.internal) <= 2,
"More than two copies of an `Rc<Internal>` at one time");
unsafe { &mut *self.internal.stream.as_ptr() }
}
}
impl<S: Stream> Stream for FieldData<S> where S::Item: BodyChunk, S::Error: StreamError {
type Item = S::Item;
type Error = S::Error;
fn poll(&mut self) -> Poll<Option<Self::Item>, Self::Error> {
self.stream_mut().body_chunk()
}
}
impl<S: Stream> Drop for FieldData<S> {
fn drop(&mut self) {
self.internal.notify_task();
}
}