Skip to main content

ntex_util/channel/
bstream.rs

1//! A buffered stream of byte chunks.
2use std::cell::{Cell, RefCell};
3use std::task::{Context, Poll};
4use std::{collections::VecDeque, fmt, future::poll_fn, pin::Pin, rc::Rc, rc::Weak};
5
6use ntex_bytes::Bytes;
7use ntex_service::ReadyNotifier;
8
9use crate::{Stream, future::OnDropFn, task::LocalWaker};
10
11/// Default high watermark, 32 KiB
12const HIGH_WATERMARK: u32 = 32_768;
13/// Default low watermark, 16 KiB
14const LOW_WATERMARK: u32 = HIGH_WATERMARK / 2;
15
16/// Indicates the current status of a byte stream.
17#[derive(Copy, Clone, Debug, PartialEq, Eq)]
18pub enum Status {
19    /// End of stream reached.
20    Eof,
21    /// Stream is ready to accept more bytes.
22    Ready,
23    /// The receiver side has been dropped.
24    Dropped,
25}
26
27/// Creates a byte stream and returns its sender and receiver.
28pub fn channel<E>() -> (Sender<E>, Receiver<E>) {
29    channel_inner(Inner::new(false))
30}
31
32/// Creates a byte stream that invalidates cached sender readiness.
33///
34/// Subscribe to `changed` in [`ntex_service::Service::bind`] before using the
35/// stream. The same notifier may be supplied to successive streams when a
36/// service's active stream changes at runtime. Installing or removing that
37/// active stream must also notify, since it changes the service's readiness.
38///
39/// Watermark and terminal-state transitions notify before waking waiters,
40/// including when the receiver is dropped after a successful readiness check.
41pub fn channel_with_notifier<E>(changed: ReadyNotifier) -> (Sender<E>, Receiver<E>) {
42    channel_inner(Inner {
43        changed: Some(changed),
44        ..Inner::new(false)
45    })
46}
47
48/// Creates a byte stream that starts at EOF.
49///
50/// Data may still be added through the returned sender. The receiver yields
51/// that buffered data first and then completes.
52pub fn eof<E>() -> (Sender<E>, Receiver<E>) {
53    channel_inner(Inner::new(true))
54}
55
56fn channel_inner<E>(inner: Inner<E>) -> (Sender<E>, Receiver<E>) {
57    let inner = Rc::new(inner);
58    (
59        Sender {
60            inner: Rc::downgrade(&inner),
61        },
62        Receiver { inner },
63    )
64}
65
66/// Creates a receiver that contains optional data and is already at EOF.
67pub fn empty<E>(data: Option<Bytes>) -> Receiver<E> {
68    let rx = Receiver {
69        inner: Rc::new(Inner::new(true)),
70    };
71    if let Some(data) = data {
72        rx.put(data);
73    }
74    rx
75}
76
77/// A buffered stream of byte chunks.
78///
79/// The receiver yields chunks in insertion order. Its configured buffer size
80/// is a cooperative backpressure threshold for the sender, not a hard memory
81/// limit.
82#[derive(Debug)]
83pub struct Receiver<E> {
84    inner: Rc<Inner<E>>,
85}
86
87impl<E> Receiver<E> {
88    /// Sets the sender backpressure watermarks.
89    ///
90    /// Once buffered data reaches `high` bytes, [`Sender::poll_ready`] stops
91    /// reporting [`Status::Ready`] until the receiver drains the buffer to
92    /// `low` bytes or less, so the sender is not woken for every consumed
93    /// chunk. `low` is capped below `high`.
94    ///
95    /// Sending does not enforce the watermarks, so producers must cooperate
96    /// by waiting for readiness. Changing the watermarks immediately updates
97    /// and, when needed, wakes sender readiness: the sender is ready if
98    /// buffered data is below `high`. The defaults are 32 KiB and 16 KiB.
99    #[inline]
100    pub fn set_watermarks(&self, high: u32, low: u32) {
101        self.inner.set_watermarks(high, low);
102    }
103
104    /// Sets the sender backpressure threshold.
105    ///
106    /// Sets the high watermark to `size` and the low watermark to half of it.
107    #[inline]
108    #[deprecated(since = "4.2.0", note = "Use `Receiver::set_watermarks()` instead")]
109    pub fn max_buffer_size(&self, size: usize) {
110        let size = u32::try_from(size).unwrap_or(u32::MAX);
111        self.inner.set_watermarks(size, size / 2);
112    }
113
114    /// Puts previously read data back at the front of the stream.
115    ///
116    /// This may grow the buffer past its readiness threshold.
117    #[inline]
118    pub fn put(&self, data: Bytes) {
119        self.inner.unread_data(data);
120    }
121
122    #[inline]
123    /// Returns `true` once EOF has been marked.
124    ///
125    /// Buffered chunks may still be available after this returns `true`.
126    pub fn is_eof(&self) -> bool {
127        self.inner.flags.get().contains(Flags::EOF)
128    }
129
130    #[inline]
131    /// Waits for and returns the next chunk, stream error, or EOF.
132    pub async fn read(&self) -> Option<Result<Bytes, E>> {
133        poll_fn(|cx| self.poll_read(cx)).await
134    }
135
136    #[inline]
137    /// Polls for the next chunk, stream error, or EOF.
138    pub fn poll_read(&self, cx: &mut Context<'_>) -> Poll<Option<Result<Bytes, E>>> {
139        if let Some(data) = self.inner.get_data() {
140            Poll::Ready(Some(Ok(data)))
141        } else if let Some(err) = self.inner.err.take() {
142            self.inner.insert_flag(Flags::EOF);
143            Poll::Ready(Some(Err(err)))
144        } else if self.inner.flags.get().intersects(Flags::EOF | Flags::ERROR) {
145            Poll::Ready(None)
146        } else {
147            self.inner.recv_task.register(cx.waker());
148            Poll::Pending
149        }
150    }
151}
152
153impl<E> Stream for Receiver<E> {
154    type Item = Result<Bytes, E>;
155
156    fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
157        self.poll_read(cx)
158    }
159}
160
161impl<E> Drop for Receiver<E> {
162    fn drop(&mut self) {
163        let flags = self.inner.flags.get();
164        self.inner.insert_flag(Flags::RECEIVER_GONE);
165        self.inner.notify(flags, false, true);
166    }
167}
168
169/// Sender side of the byte stream.
170///
171/// Clones share one readiness registration. If several clones poll readiness,
172/// the most recently registered task is the one that will be woken.
173#[derive(Debug)]
174pub struct Sender<E> {
175    inner: Weak<Inner<E>>,
176}
177
178impl<E> Clone for Sender<E> {
179    fn clone(&self) -> Self {
180        Self {
181            inner: self.inner.clone(),
182        }
183    }
184}
185
186impl<E> Drop for Sender<E> {
187    fn drop(&mut self) {
188        if self.inner.weak_count() == 1
189            && let Some(shared) = self.inner.upgrade()
190        {
191            let flags = shared.flags.get();
192            shared.insert_flag(Flags::EOF | Flags::SENDER_GONE);
193            // a pending read completes with EOF
194            shared.notify(flags, true, true);
195        }
196    }
197}
198
199impl<E> Sender<E> {
200    /// Returns `true` if the receiver has been dropped.
201    pub fn is_closed(&self) -> bool {
202        self.inner
203            .upgrade()
204            .is_none_or(|shared| shared.flags.get().contains(Flags::RECEIVER_GONE))
205    }
206
207    /// Stores a terminal stream error and wakes both sides.
208    pub fn set_error(&self, err: E) {
209        if let Some(shared) = self.inner.upgrade() {
210            shared.set_error(err);
211        }
212    }
213
214    /// Marks the stream as EOF and wakes both sides.
215    pub fn feed_eof(&self) {
216        if let Some(shared) = self.inner.upgrade() {
217            shared.feed_eof();
218        }
219    }
220
221    /// Adds a chunk to the stream.
222    ///
223    /// This method does not enforce the configured backpressure threshold.
224    pub fn feed_data(&self, data: Bytes) {
225        if let Some(shared) = self.inner.upgrade() {
226            shared.feed_data(data);
227        }
228    }
229
230    /// Waits until the stream needs more data or reaches a terminal state.
231    pub async fn ready(&self) -> Status {
232        poll_fn(|cx| self.poll_ready(cx)).await
233    }
234
235    /// Polls until the stream needs more data or reaches a terminal state.
236    ///
237    /// Terminal states take precedence: [`Status::Dropped`] is returned once
238    /// the receiver is gone or an error was set, [`Status::Eof`] after EOF.
239    pub fn poll_ready(&self, cx: &mut Context<'_>) -> Poll<Status> {
240        if let Some(shared) = self.inner.upgrade() {
241            let status = shared.flags.get().status();
242            if status.is_pending() {
243                shared.send_task.register(cx.waker());
244            }
245            status
246        } else {
247            // receiver is gone
248            Poll::Ready(Status::Dropped)
249        }
250    }
251}
252
253bitflags::bitflags! {
254    #[derive(Copy, Clone, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
255    struct Flags: u8 {
256        const EOF         = 0b0000_0001;
257        const ERROR       = 0b0000_0010;
258        const NEED_READ   = 0b0000_0100;
259        const SENDER_GONE = 0b0000_1000;
260        const RECEIVER_GONE = 0b0001_0000;
261    }
262}
263
264impl Flags {
265    fn status(self) -> Poll<Status> {
266        if self.intersects(Self::SENDER_GONE | Self::RECEIVER_GONE | Self::ERROR) {
267            Poll::Ready(Status::Dropped)
268        } else if self.contains(Self::EOF) {
269            Poll::Ready(Status::Eof)
270        } else if self.contains(Self::NEED_READ) {
271            Poll::Ready(Status::Ready)
272        } else {
273            Poll::Pending
274        }
275    }
276}
277
278struct Inner<E> {
279    len: Cell<usize>,
280    flags: Cell<Flags>,
281    err: Cell<Option<E>>,
282    items: RefCell<VecDeque<Bytes>>,
283    recv_task: LocalWaker,
284    send_task: LocalWaker,
285    high_watermark: Cell<u32>,
286    low_watermark: Cell<u32>,
287    changed: Option<ReadyNotifier>,
288}
289
290impl<E> Inner<E> {
291    fn new(eof: bool) -> Self {
292        let flags = if eof { Flags::EOF } else { Flags::NEED_READ };
293        Inner {
294            flags: Cell::new(flags),
295            len: Cell::new(0),
296            err: Cell::new(None),
297            items: RefCell::new(VecDeque::new()),
298            recv_task: LocalWaker::new(),
299            send_task: LocalWaker::new(),
300            high_watermark: Cell::new(HIGH_WATERMARK),
301            low_watermark: Cell::new(LOW_WATERMARK),
302            changed: None,
303        }
304    }
305
306    fn insert_flag(&self, f: Flags) {
307        let mut flags = self.flags.get();
308        flags.insert(f);
309        self.flags.set(flags);
310    }
311
312    fn remove_flag(&self, f: Flags) {
313        let mut flags = self.flags.get();
314        flags.remove(f);
315        self.flags.set(flags);
316    }
317
318    fn notify(&self, previous: Flags, recv: bool, send: bool) {
319        let _wake = OnDropFn::new(|| {
320            if recv {
321                self.recv_task.wake();
322            }
323            if send {
324                self.send_task.wake();
325            }
326        });
327        if previous.status() != self.flags.get().status()
328            && let Some(changed) = &self.changed
329        {
330            changed.notify();
331        }
332    }
333
334    fn set_watermarks(&self, high: u32, low: u32) {
335        self.high_watermark.set(high);
336        self.low_watermark.set(low.min(high.saturating_sub(1)));
337
338        let flags = self.flags.get();
339        if flags.intersects(Flags::EOF | Flags::ERROR | Flags::SENDER_GONE) {
340            return;
341        }
342
343        if self.len.get() < high as usize {
344            if !flags.contains(Flags::NEED_READ) {
345                self.insert_flag(Flags::NEED_READ);
346                self.notify(flags, false, true);
347            }
348        } else {
349            self.remove_flag(Flags::NEED_READ);
350            self.notify(flags, false, false);
351        }
352    }
353
354    fn set_error(&self, err: E) {
355        let flags = self.flags.get();
356        self.err.set(Some(err));
357        self.insert_flag(Flags::ERROR);
358        self.notify(flags, true, true);
359    }
360
361    fn feed_eof(&self) {
362        let flags = self.flags.get();
363        self.insert_flag(Flags::EOF);
364        self.notify(flags, true, true);
365    }
366
367    fn feed_data(&self, data: Bytes) {
368        let flags = self.flags.get();
369        let len = self.len.get() + data.len();
370        self.len.set(len);
371        self.items.borrow_mut().push_back(data);
372        if len >= self.high_watermark.get() as usize {
373            self.remove_flag(Flags::NEED_READ);
374        }
375        self.notify(flags, true, false);
376    }
377
378    fn get_data(&self) -> Option<Bytes> {
379        let data = self.items.borrow_mut().pop_front();
380        data.inspect(|data| {
381            let flags = self.flags.get();
382            let len = self.len.get() - data.len();
383
384            // wake up sender once the buffer is drained to the low watermark
385            self.len.set(len);
386            if len <= self.low_watermark.get() as usize {
387                self.insert_flag(Flags::NEED_READ);
388                self.notify(flags, false, true);
389            }
390        })
391    }
392
393    fn unread_data(&self, data: Bytes) {
394        let flags = self.flags.get();
395        if !data.is_empty() {
396            self.len.set(self.len.get() + data.len());
397            self.items.borrow_mut().push_front(data);
398            if self.len.get() >= self.high_watermark.get() as usize {
399                self.remove_flag(Flags::NEED_READ);
400            }
401            self.notify(flags, false, false);
402        }
403    }
404}
405
406impl<E> fmt::Debug for Inner<E> {
407    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
408        f.debug_struct("Inner")
409            .field("len", &self.len)
410            .field("flags", &self.flags)
411            .field("items", &self.items.borrow())
412            .field("high_watermark", &self.high_watermark)
413            .field("low_watermark", &self.low_watermark)
414            .field("recv_task", &self.recv_task)
415            .field("send_task", &self.send_task)
416            .finish()
417    }
418}
419
420#[cfg(test)]
421mod tests {
422    use ntex_service::{BindCtx, Ctx, Pipeline, ReadyCallback, Service};
423
424    use super::*;
425    use crate::future::lazy;
426
427    struct SenderService(Sender<()>, ReadyNotifier);
428
429    impl Service<(), Bytes> for SenderService {
430        type Res = ();
431        type Error = Status;
432
433        fn bind(&self, ctx: BindCtx<'_>) {
434            ctx.subscribe(&self.1);
435        }
436
437        async fn ready(&self, _: Ctx<'_, Self>) -> Result<(), Status> {
438            match self.0.ready().await {
439                Status::Ready => Ok(()),
440                status => Err(status),
441            }
442        }
443
444        async fn call(&self, data: Bytes, _: Ctx<'_, Self>) -> Result<(), Status> {
445            self.0.feed_data(data);
446            Ok(())
447        }
448    }
449
450    #[ntex::test]
451    async fn cached_sender_readiness_tracks_watermarks() {
452        let changed = ReadyNotifier::new();
453        let (tx, rx) = channel_with_notifier(changed.clone());
454        rx.set_watermarks(4, 2);
455        let srv = Pipeline::new((), SenderService(tx, changed));
456
457        srv.call(Bytes::from_static(b"ab")).await.unwrap();
458        assert!(srv.is_ready());
459        srv.call(Bytes::from_static(b"cd")).await.unwrap();
460        assert!(!srv.is_ready());
461        assert!(lazy(|cx| srv.poll_ready(cx)).await.is_pending());
462        assert_eq!(rx.read().await, Some(Ok(Bytes::from_static(b"ab"))));
463        srv.ready().await.unwrap();
464
465        rx.put(Bytes::from_static(b"ef"));
466        assert!(!srv.is_ready());
467        assert!(lazy(|cx| srv.poll_ready(cx)).await.is_pending());
468        rx.set_watermarks(8, 4);
469        srv.ready().await.unwrap();
470        rx.set_watermarks(4, 2);
471        assert!(!srv.is_ready());
472        assert!(lazy(|cx| srv.poll_ready(cx)).await.is_pending());
473    }
474
475    #[ntex::test]
476    async fn cached_sender_readiness_tracks_terminal_states() {
477        for status in [Status::Eof, Status::Dropped] {
478            let changed = ReadyNotifier::new();
479            let (tx, _rx) = channel_with_notifier(changed.clone());
480            let srv = Pipeline::new((), SenderService(tx.clone(), changed));
481            srv.ready().await.unwrap();
482            if status == Status::Eof {
483                tx.feed_eof();
484            } else {
485                tx.set_error(());
486            }
487            assert!(!srv.is_ready());
488            assert_eq!(srv.ready().await, Err(status));
489        }
490
491        let changed = ReadyNotifier::new();
492        let (tx, rx) = channel_with_notifier(changed.clone());
493        let srv = Pipeline::new((), SenderService(tx.clone(), changed));
494        let on_drop = ReadyCallback::new(move || {
495            assert!(tx.is_closed());
496            assert_eq!(
497                tx.poll_ready(&mut Context::from_waker(std::task::Waker::noop())),
498                Poll::Ready(Status::Dropped)
499            );
500        });
501        srv.on_notify(&on_drop);
502        srv.ready().await.unwrap();
503        drop(rx);
504        assert!(!srv.is_ready());
505        assert_eq!(srv.ready().await, Err(Status::Dropped));
506    }
507
508    #[ntex::test]
509    async fn callback_panic_does_not_skip_stream_wakes() {
510        use std::panic::{AssertUnwindSafe, catch_unwind};
511        use std::sync::{Arc, atomic::AtomicUsize, atomic::Ordering};
512        use std::task::{Wake, Waker};
513
514        #[derive(Default)]
515        struct WakeCount(AtomicUsize);
516        impl Wake for WakeCount {
517            fn wake(self: Arc<Self>) {
518                self.0.fetch_add(1, Ordering::Relaxed);
519            }
520        }
521
522        let changed = ReadyNotifier::new();
523        let (tx, rx) = channel_with_notifier(changed.clone());
524        rx.set_watermarks(1, 0);
525        let srv = Pipeline::new((), SenderService(tx.clone(), changed));
526        srv.ready().await.unwrap();
527        let armed = Rc::new(Cell::new(true));
528        let armed2 = armed.clone();
529        let callback = ReadyCallback::new(move || {
530            assert!(!armed2.replace(false), "callback panic");
531        });
532        srv.on_notify(&callback);
533        let wakes = Arc::new(WakeCount::default());
534        let waker = Waker::from(wakes.clone());
535        let mut cx = Context::from_waker(&waker);
536
537        assert!(rx.poll_read(&mut cx).is_pending());
538        assert!(catch_unwind(AssertUnwindSafe(|| tx.feed_data(b"x".into()))).is_err());
539        assert!(!srv.is_ready());
540        assert_eq!(wakes.0.load(Ordering::Relaxed), 1);
541        assert!(tx.poll_ready(&mut cx).is_pending());
542
543        armed.set(true);
544        assert!(catch_unwind(AssertUnwindSafe(|| rx.poll_read(&mut cx))).is_err());
545        assert_eq!(wakes.0.load(Ordering::Relaxed), 2);
546        srv.ready().await.unwrap();
547    }
548
549    #[ntex::test]
550    async fn test_sender_drop_wakes_receiver() {
551        let (tx, rx) = channel::<()>();
552        let handle = crate::spawn(async move { rx.read().await.is_none() });
553        crate::time::sleep(crate::time::Millis(10)).await;
554
555        drop(tx);
556        let res = crate::time::timeout(crate::time::Millis(1000), handle).await;
557        assert!(matches!(res, Ok(Ok(true))));
558    }
559
560    #[ntex::test]
561    async fn test_eof() {
562        let (tx, rx) = eof::<()>();
563        rx.set_watermarks(100, 50);
564        assert!(rx.read().await.is_none());
565        assert_eq!(tx.ready().await, Status::Eof);
566    }
567
568    #[ntex::test]
569    async fn test_closed() {
570        // drop receiver
571        let (tx, rx) = channel::<()>();
572        assert!(!tx.is_closed());
573        drop(rx);
574        assert!(tx.is_closed());
575
576        // drop sender
577        let (tx, rx) = channel::<()>();
578        drop(tx);
579        assert_eq!(rx.read().await, None);
580    }
581
582    #[ntex::test]
583    async fn test_unread_data() {
584        let (_, payload) = channel::<()>();
585
586        payload.put(Bytes::from("data"));
587        assert_eq!(payload.inner.len.get(), 4);
588        assert_eq!(
589            Bytes::from("data"),
590            poll_fn(|cx| payload.poll_read(cx)).await.unwrap().unwrap()
591        );
592    }
593
594    #[ntex::test]
595    async fn buffer_size_updates_sender_readiness() {
596        let (tx, rx) = channel::<()>();
597        rx.set_watermarks(4, 2);
598        tx.feed_data(Bytes::from_static(b"data"));
599
600        assert!(lazy(|cx| tx.poll_ready(cx)).await.is_pending());
601        assert!(rx.inner.send_task.is_set());
602
603        rx.set_watermarks(5, 2);
604        assert!(!rx.inner.send_task.is_set());
605        assert_eq!(
606            lazy(|cx| tx.poll_ready(cx)).await,
607            Poll::Ready(Status::Ready)
608        );
609
610        rx.set_watermarks(4, 2);
611        assert!(lazy(|cx| tx.poll_ready(cx)).await.is_pending());
612    }
613
614    #[ntex::test]
615    async fn sender_resumes_at_low_watermark() {
616        let (tx, rx) = channel::<()>();
617        rx.set_watermarks(8, 4);
618        for _ in 0..4 {
619            tx.feed_data(Bytes::from_static(b"da"));
620        }
621        assert!(lazy(|cx| tx.poll_ready(cx)).await.is_pending());
622
623        // above the low watermark
624        assert!(rx.read().await.is_some());
625        assert!(rx.inner.send_task.is_set());
626        assert!(lazy(|cx| tx.poll_ready(cx)).await.is_pending());
627
628        // at the low watermark
629        assert!(rx.read().await.is_some());
630        assert!(!rx.inner.send_task.is_set());
631        assert_eq!(
632            lazy(|cx| tx.poll_ready(cx)).await,
633            Poll::Ready(Status::Ready)
634        );
635
636        // low watermark is capped below the high watermark
637        let (tx, rx) = channel::<()>();
638        rx.set_watermarks(4, 10);
639        for _ in 0..3 {
640            tx.feed_data(Bytes::from_static(b"da"));
641        }
642        assert!(rx.read().await.is_some());
643        assert!(lazy(|cx| tx.poll_ready(cx)).await.is_pending());
644        assert!(rx.read().await.is_some());
645        assert_eq!(
646            lazy(|cx| tx.poll_ready(cx)).await,
647            Poll::Ready(Status::Ready)
648        );
649    }
650
651    #[ntex::test]
652    async fn custom_low_watermark() {
653        let (tx, rx) = channel::<()>();
654        rx.set_watermarks(8, 2);
655        for _ in 0..4 {
656            tx.feed_data(Bytes::from_static(b"da"));
657        }
658        assert!(rx.read().await.is_some());
659        assert!(rx.read().await.is_some());
660        assert!(lazy(|cx| tx.poll_ready(cx)).await.is_pending());
661        assert!(rx.read().await.is_some());
662        assert_eq!(
663            lazy(|cx| tx.poll_ready(cx)).await,
664            Poll::Ready(Status::Ready)
665        );
666    }
667
668    #[ntex::test]
669    #[allow(deprecated)]
670    async fn deprecated_max_buffer_size() {
671        let (_tx, rx) = channel::<()>();
672        rx.max_buffer_size(10);
673        assert_eq!(rx.inner.high_watermark.get(), 10);
674        assert_eq!(rx.inner.low_watermark.get(), 5);
675    }
676
677    #[ntex::test]
678    async fn test_sender_clone() {
679        let (sender, payload) = channel::<()>();
680        assert!(!payload.is_eof());
681        let sender2 = sender.clone();
682        assert!(!payload.is_eof());
683        drop(sender2);
684        assert!(!payload.is_eof());
685        drop(sender);
686        assert!(payload.is_eof());
687    }
688
689    #[ntex::test]
690    async fn test_ready_terminal_states() {
691        let (tx, _rx) = channel::<()>();
692        assert_eq!(tx.ready().await, Status::Ready);
693        tx.set_error(());
694        assert_eq!(tx.ready().await, Status::Dropped);
695
696        let (tx, _rx) = channel::<()>();
697        tx.feed_eof();
698        assert_eq!(tx.ready().await, Status::Eof);
699
700        let (tx, rx) = channel::<()>();
701        drop(rx);
702        assert_eq!(tx.ready().await, Status::Dropped);
703    }
704
705    #[ntex::test]
706    async fn test_empty() {
707        let rx = empty::<()>(None);
708        assert!(rx.is_eof());
709        assert!(rx.read().await.is_none());
710
711        let mut rx = empty::<()>(Some(Bytes::from_static(b"data")));
712        assert!(format!("{rx:?}").contains("high_watermark"));
713        assert_eq!(
714            crate::future::stream_recv(&mut rx).await.unwrap().unwrap(),
715            Bytes::from_static(b"data")
716        );
717        assert!(crate::future::stream_recv(&mut rx).await.is_none());
718    }
719
720    #[ntex::test]
721    async fn test_error() {
722        let (tx, rx) = channel::<&'static str>();
723        tx.feed_data(Bytes::from_static(b"data"));
724        tx.set_error("err");
725
726        // buffered data is returned before the error, then eof
727        assert_eq!(
728            rx.read().await.unwrap().unwrap(),
729            Bytes::from_static(b"data")
730        );
731        assert_eq!(rx.read().await.unwrap().unwrap_err(), "err");
732        assert!(rx.is_eof());
733        assert!(rx.read().await.is_none());
734    }
735}