2017-12-19 09:18:57 +01:00
|
|
|
//! Payload stream
|
2018-04-14 01:02:01 +02:00
|
|
|
use std::cell::RefCell;
|
|
|
|
use std::collections::VecDeque;
|
2019-11-15 10:54:11 +01:00
|
|
|
use std::pin::Pin;
|
2018-04-14 01:02:01 +02:00
|
|
|
use std::rc::{Rc, Weak};
|
2021-03-07 22:23:42 +01:00
|
|
|
use std::task::{Context, Poll, Waker};
|
2017-10-09 05:16:48 +02:00
|
|
|
|
2019-04-03 12:20:20 +02:00
|
|
|
use bytes::Bytes;
|
2019-12-13 06:24:57 +01:00
|
|
|
use futures_core::Stream;
|
2019-03-27 05:54:57 +01:00
|
|
|
|
2018-12-06 23:32:52 +01:00
|
|
|
use crate::error::PayloadError;
|
2017-10-27 08:14:33 +02:00
|
|
|
|
2018-03-12 18:01:56 +01:00
|
|
|
/// max buffer size 32k
|
|
|
|
pub(crate) const MAX_BUFFER_SIZE: usize = 32_768;
|
|
|
|
|
2018-02-28 01:08:57 +01:00
|
|
|
#[derive(Debug, PartialEq)]
|
2019-04-03 21:28:58 +02:00
|
|
|
pub enum PayloadStatus {
|
2018-02-28 01:08:57 +01:00
|
|
|
Read,
|
|
|
|
Pause,
|
|
|
|
Dropped,
|
|
|
|
}
|
|
|
|
|
2017-12-19 09:29:25 +01:00
|
|
|
/// Buffered stream of bytes chunks
|
2017-10-09 05:16:48 +02:00
|
|
|
///
|
2018-04-14 01:02:01 +02:00
|
|
|
/// Payload stores chunks in a vector. First chunk can be received with
|
|
|
|
/// `.readany()` method. Payload stream is not thread safe. Payload does not
|
|
|
|
/// notify current task when new data is available.
|
2017-12-19 09:29:25 +01:00
|
|
|
///
|
2018-10-05 20:04:59 +02:00
|
|
|
/// Payload stream can be used as `Response` body stream.
|
2017-10-19 08:43:50 +02:00
|
|
|
#[derive(Debug)]
|
2017-10-09 05:16:48 +02:00
|
|
|
pub struct Payload {
|
|
|
|
inner: Rc<RefCell<Inner>>,
|
|
|
|
}
|
|
|
|
|
|
|
|
impl Payload {
|
2017-12-19 06:58:38 +01:00
|
|
|
/// Create payload stream.
|
|
|
|
///
|
2018-04-14 01:02:01 +02:00
|
|
|
/// This method construct two objects responsible for bytes stream
|
|
|
|
/// generation.
|
2017-12-19 06:58:38 +01:00
|
|
|
///
|
|
|
|
/// * `PayloadSender` - *Sender* side of the stream
|
|
|
|
///
|
|
|
|
/// * `Payload` - *Receiver* side of the stream
|
2019-01-29 19:14:00 +01:00
|
|
|
pub fn create(eof: bool) -> (PayloadSender, Payload) {
|
2017-10-09 05:16:48 +02:00
|
|
|
let shared = Rc::new(RefCell::new(Inner::new(eof)));
|
|
|
|
|
2018-04-14 01:02:01 +02:00
|
|
|
(
|
|
|
|
PayloadSender {
|
|
|
|
inner: Rc::downgrade(&shared),
|
|
|
|
},
|
2018-04-29 18:09:08 +02:00
|
|
|
Payload { inner: shared },
|
2018-04-14 01:02:01 +02:00
|
|
|
)
|
2017-10-09 05:16:48 +02:00
|
|
|
}
|
|
|
|
|
2017-11-27 04:00:57 +01:00
|
|
|
/// Create empty payload
|
|
|
|
#[doc(hidden)]
|
|
|
|
pub fn empty() -> Payload {
|
2018-04-14 01:02:01 +02:00
|
|
|
Payload {
|
|
|
|
inner: Rc::new(RefCell::new(Inner::new(true))),
|
|
|
|
}
|
2017-11-27 04:00:57 +01:00
|
|
|
}
|
|
|
|
|
2017-10-09 05:16:48 +02:00
|
|
|
/// Length of the data in this payload
|
2018-06-25 06:58:04 +02:00
|
|
|
#[cfg(test)]
|
2017-10-09 05:16:48 +02:00
|
|
|
pub fn len(&self) -> usize {
|
|
|
|
self.inner.borrow().len()
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Is payload empty
|
2018-06-25 06:58:04 +02:00
|
|
|
#[cfg(test)]
|
2017-10-09 05:16:48 +02:00
|
|
|
pub fn is_empty(&self) -> bool {
|
|
|
|
self.inner.borrow().len() == 0
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Put unused data back to payload
|
2018-01-11 06:02:28 +01:00
|
|
|
#[inline]
|
2017-10-14 01:33:23 +02:00
|
|
|
pub fn unread_data(&mut self, data: Bytes) {
|
2017-10-09 05:16:48 +02:00
|
|
|
self.inner.borrow_mut().unread_data(data);
|
|
|
|
}
|
2019-11-15 10:54:11 +01:00
|
|
|
|
|
|
|
#[inline]
|
|
|
|
pub fn readany(
|
|
|
|
&mut self,
|
2019-12-07 19:46:51 +01:00
|
|
|
cx: &mut Context<'_>,
|
2019-11-15 10:54:11 +01:00
|
|
|
) -> Poll<Option<Result<Bytes, PayloadError>>> {
|
|
|
|
self.inner.borrow_mut().readany(cx)
|
|
|
|
}
|
2017-10-09 05:16:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Stream for Payload {
|
2019-11-15 10:54:11 +01:00
|
|
|
type Item = Result<Bytes, PayloadError>;
|
2017-10-09 05:16:48 +02:00
|
|
|
|
2019-11-15 10:54:11 +01:00
|
|
|
fn poll_next(
|
|
|
|
self: Pin<&mut Self>,
|
2019-12-07 19:46:51 +01:00
|
|
|
cx: &mut Context<'_>,
|
2019-11-15 10:54:11 +01:00
|
|
|
) -> Poll<Option<Result<Bytes, PayloadError>>> {
|
|
|
|
self.inner.borrow_mut().readany(cx)
|
2017-12-19 09:18:57 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-12-19 06:58:38 +01:00
|
|
|
/// Sender part of the payload stream
|
|
|
|
pub struct PayloadSender {
|
2017-10-09 05:16:48 +02:00
|
|
|
inner: Weak<RefCell<Inner>>,
|
|
|
|
}
|
|
|
|
|
2019-04-07 19:29:26 +02:00
|
|
|
impl PayloadSender {
|
2018-03-09 02:19:50 +01:00
|
|
|
#[inline]
|
2019-04-07 19:29:26 +02:00
|
|
|
pub fn set_error(&mut self, err: PayloadError) {
|
2017-10-14 01:33:23 +02:00
|
|
|
if let Some(shared) = self.inner.upgrade() {
|
|
|
|
shared.borrow_mut().set_error(err)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-09 02:19:50 +01:00
|
|
|
#[inline]
|
2019-04-07 19:29:26 +02:00
|
|
|
pub fn feed_eof(&mut self) {
|
2017-10-09 05:16:48 +02:00
|
|
|
if let Some(shared) = self.inner.upgrade() {
|
|
|
|
shared.borrow_mut().feed_eof()
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-09 02:19:50 +01:00
|
|
|
#[inline]
|
2019-04-07 19:29:26 +02:00
|
|
|
pub fn feed_data(&mut self, data: Bytes) {
|
2017-10-09 05:16:48 +02:00
|
|
|
if let Some(shared) = self.inner.upgrade() {
|
|
|
|
shared.borrow_mut().feed_data(data)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-10 01:20:10 +01:00
|
|
|
#[inline]
|
2019-12-07 19:46:51 +01:00
|
|
|
pub fn need_read(&self, cx: &mut Context<'_>) -> PayloadStatus {
|
2018-02-28 01:08:57 +01:00
|
|
|
// we check need_read only if Payload (other side) is alive,
|
|
|
|
// otherwise always return true (consume payload)
|
2017-11-06 10:24:49 +01:00
|
|
|
if let Some(shared) = self.inner.upgrade() {
|
2018-02-28 01:08:57 +01:00
|
|
|
if shared.borrow().need_read {
|
|
|
|
PayloadStatus::Read
|
|
|
|
} else {
|
2021-03-07 22:23:42 +01:00
|
|
|
shared.borrow_mut().register_io(cx);
|
2018-02-28 01:08:57 +01:00
|
|
|
PayloadStatus::Pause
|
|
|
|
}
|
2017-11-06 10:24:49 +01:00
|
|
|
} else {
|
2018-02-28 01:08:57 +01:00
|
|
|
PayloadStatus::Dropped
|
2017-11-06 10:24:49 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-10-19 08:43:50 +02:00
|
|
|
#[derive(Debug)]
|
2017-10-09 05:16:48 +02:00
|
|
|
struct Inner {
|
|
|
|
len: usize,
|
|
|
|
eof: bool,
|
2017-10-14 01:33:23 +02:00
|
|
|
err: Option<PayloadError>,
|
2018-02-27 05:07:22 +01:00
|
|
|
need_read: bool,
|
2017-10-09 05:16:48 +02:00
|
|
|
items: VecDeque<Bytes>,
|
2021-03-07 22:23:42 +01:00
|
|
|
task: Option<Waker>,
|
|
|
|
io_task: Option<Waker>,
|
2017-10-09 05:16:48 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
impl Inner {
|
|
|
|
fn new(eof: bool) -> Self {
|
|
|
|
Inner {
|
2018-02-26 23:33:56 +01:00
|
|
|
eof,
|
2017-10-09 05:16:48 +02:00
|
|
|
len: 0,
|
2017-10-14 01:33:23 +02:00
|
|
|
err: None,
|
2017-10-09 05:16:48 +02:00
|
|
|
items: VecDeque::new(),
|
2018-03-03 05:47:23 +01:00
|
|
|
need_read: true,
|
2021-03-07 22:23:42 +01:00
|
|
|
task: None,
|
|
|
|
io_task: None,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Wake up future waiting for payload data to be available.
|
|
|
|
fn wake(&mut self) {
|
|
|
|
if let Some(waker) = self.task.take() {
|
|
|
|
waker.wake();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Wake up future feeding data to Payload.
|
|
|
|
fn wake_io(&mut self) {
|
|
|
|
if let Some(waker) = self.io_task.take() {
|
|
|
|
waker.wake();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/// Register future waiting data from payload.
|
|
|
|
/// Waker would be used in `Inner::wake`
|
|
|
|
fn register(&mut self, cx: &mut Context<'_>) {
|
|
|
|
if self
|
|
|
|
.task
|
|
|
|
.as_ref()
|
|
|
|
.map(|w| !cx.waker().will_wake(w))
|
|
|
|
.unwrap_or(true)
|
|
|
|
{
|
|
|
|
self.task = Some(cx.waker().clone());
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// Register future feeding data to payload.
|
|
|
|
/// Waker would be used in `Inner::wake_io`
|
|
|
|
fn register_io(&mut self, cx: &mut Context<'_>) {
|
|
|
|
if self
|
|
|
|
.io_task
|
|
|
|
.as_ref()
|
|
|
|
.map(|w| !cx.waker().will_wake(w))
|
|
|
|
.unwrap_or(true)
|
|
|
|
{
|
|
|
|
self.io_task = Some(cx.waker().clone());
|
2017-10-09 05:16:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-03-09 02:19:50 +01:00
|
|
|
#[inline]
|
2017-10-14 01:33:23 +02:00
|
|
|
fn set_error(&mut self, err: PayloadError) {
|
|
|
|
self.err = Some(err);
|
|
|
|
}
|
|
|
|
|
2018-03-09 02:19:50 +01:00
|
|
|
#[inline]
|
2017-10-09 05:16:48 +02:00
|
|
|
fn feed_eof(&mut self) {
|
|
|
|
self.eof = true;
|
|
|
|
}
|
|
|
|
|
2018-03-09 02:19:50 +01:00
|
|
|
#[inline]
|
2017-10-09 05:16:48 +02:00
|
|
|
fn feed_data(&mut self, data: Bytes) {
|
|
|
|
self.len += data.len();
|
|
|
|
self.items.push_back(data);
|
2019-04-07 19:40:45 +02:00
|
|
|
self.need_read = self.len < MAX_BUFFER_SIZE;
|
2021-03-07 22:23:42 +01:00
|
|
|
self.wake();
|
2017-10-09 05:16:48 +02:00
|
|
|
}
|
|
|
|
|
2018-06-25 06:58:04 +02:00
|
|
|
#[cfg(test)]
|
2017-10-09 05:16:48 +02:00
|
|
|
fn len(&self) -> usize {
|
|
|
|
self.len
|
|
|
|
}
|
|
|
|
|
2019-11-15 10:54:11 +01:00
|
|
|
fn readany(
|
|
|
|
&mut self,
|
2019-12-07 19:46:51 +01:00
|
|
|
cx: &mut Context<'_>,
|
2019-11-15 10:54:11 +01:00
|
|
|
) -> Poll<Option<Result<Bytes, PayloadError>>> {
|
2017-10-09 05:16:48 +02:00
|
|
|
if let Some(data) = self.items.pop_front() {
|
|
|
|
self.len -= data.len();
|
2019-04-07 19:40:45 +02:00
|
|
|
self.need_read = self.len < MAX_BUFFER_SIZE;
|
2019-03-27 05:54:57 +01:00
|
|
|
|
2019-11-15 10:54:11 +01:00
|
|
|
if self.need_read && !self.eof {
|
2021-03-07 22:23:42 +01:00
|
|
|
self.register(cx);
|
2018-03-13 00:29:13 +01:00
|
|
|
}
|
2021-03-07 22:23:42 +01:00
|
|
|
self.wake_io();
|
2019-11-15 10:54:11 +01:00
|
|
|
Poll::Ready(Some(Ok(data)))
|
2017-10-14 01:33:23 +02:00
|
|
|
} else if let Some(err) = self.err.take() {
|
2019-11-15 10:54:11 +01:00
|
|
|
Poll::Ready(Some(Err(err)))
|
2018-02-10 01:20:10 +01:00
|
|
|
} else if self.eof {
|
2019-11-15 10:54:11 +01:00
|
|
|
Poll::Ready(None)
|
2017-10-09 05:16:48 +02:00
|
|
|
} else {
|
2018-02-27 05:07:22 +01:00
|
|
|
self.need_read = true;
|
2021-03-07 22:23:42 +01:00
|
|
|
self.register(cx);
|
|
|
|
self.wake_io();
|
2019-11-15 10:54:11 +01:00
|
|
|
Poll::Pending
|
2017-10-09 05:16:48 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-04 17:07:44 +01:00
|
|
|
fn unread_data(&mut self, data: Bytes) {
|
2017-10-09 05:16:48 +02:00
|
|
|
self.len += data.len();
|
2017-12-21 05:30:54 +01:00
|
|
|
self.items.push_front(data);
|
2017-10-09 05:16:48 +02:00
|
|
|
}
|
|
|
|
}
|
2017-10-23 04:58:50 +02:00
|
|
|
|
|
|
|
#[cfg(test)]
|
2017-10-23 06:40:41 +02:00
|
|
|
mod tests {
|
2017-10-23 04:58:50 +02:00
|
|
|
use super::*;
|
2019-12-13 06:24:57 +01:00
|
|
|
use futures_util::future::poll_fn;
|
2017-10-23 04:58:50 +02:00
|
|
|
|
2019-11-26 06:25:50 +01:00
|
|
|
#[actix_rt::test]
|
|
|
|
async fn test_unread_data() {
|
|
|
|
let (_, mut payload) = Payload::create(false);
|
2019-11-19 13:54:19 +01:00
|
|
|
|
2019-11-26 06:25:50 +01:00
|
|
|
payload.unread_data(Bytes::from("data"));
|
|
|
|
assert!(!payload.is_empty());
|
|
|
|
assert_eq!(payload.len(), 4);
|
2019-11-19 13:54:19 +01:00
|
|
|
|
2019-11-26 06:25:50 +01:00
|
|
|
assert_eq!(
|
|
|
|
Bytes::from("data"),
|
|
|
|
poll_fn(|cx| payload.readany(cx)).await.unwrap().unwrap()
|
|
|
|
);
|
2017-10-23 05:19:20 +02:00
|
|
|
}
|
2017-10-23 04:58:50 +02:00
|
|
|
}
|