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