#![no_std]
#![doc = include_str!("../README.md")]
use core::pin::Pin;
use core::task::{Context, Poll};
pub trait OrderedStream {
type Ordering: Ord;
type Data;
fn poll_next_before(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
before: Option<&Self::Ordering>,
) -> Poll<PollResult<Self::Ordering, Self::Data>>;
fn position_hint(&self) -> Option<MaybeBorrowed<'_, Self::Ordering>> {
None
}
fn size_hint(&self) -> (usize, Option<usize>) {
(0, None)
}
}
#[derive(Debug)]
pub enum MaybeBorrowed<'a, T> {
Borrowed(&'a T),
Owned(T),
}
impl<'a, T> AsRef<T> for MaybeBorrowed<'a, T> {
fn as_ref(&self) -> &T {
match self {
Self::Borrowed(t) => t,
Self::Owned(t) => t,
}
}
}
impl<'a, T> core::ops::Deref for MaybeBorrowed<'a, T> {
type Target = T;
fn deref(&self) -> &T {
match self {
Self::Borrowed(t) => t,
Self::Owned(t) => t,
}
}
}
impl<P> OrderedStream for Pin<P>
where
P: core::ops::DerefMut + Unpin,
P::Target: OrderedStream,
{
type Data = <P::Target as OrderedStream>::Data;
type Ordering = <P::Target as OrderedStream>::Ordering;
fn poll_next_before(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
before: Option<&Self::Ordering>,
) -> Poll<PollResult<Self::Ordering, Self::Data>> {
self.get_mut().as_mut().poll_next_before(cx, before)
}
fn position_hint(&self) -> Option<MaybeBorrowed<'_, Self::Ordering>> {
(**self).position_hint()
}
fn size_hint(&self) -> (usize, Option<usize>) {
(**self).size_hint()
}
}
impl<S> OrderedStream for Option<S>
where
S: OrderedStream,
{
type Data = S::Data;
type Ordering = S::Ordering;
fn poll_next_before(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
before: Option<&Self::Ordering>,
) -> Poll<PollResult<Self::Ordering, Self::Data>> {
match self.as_pin_mut() {
Some(s) => s.poll_next_before(cx, before),
None => Poll::Ready(PollResult::Terminated),
}
}
fn position_hint(&self) -> Option<MaybeBorrowed<'_, Self::Ordering>> {
self.as_ref().and_then(|s| s.position_hint())
}
fn size_hint(&self) -> (usize, Option<usize>) {
self.as_ref().map_or((0, Some(0)), |s| s.size_hint())
}
}
pub trait FusedOrderedStream: OrderedStream {
fn is_terminated(&self) -> bool;
}
impl<P> FusedOrderedStream for Pin<P>
where
P: core::ops::DerefMut + Unpin,
P::Target: FusedOrderedStream,
{
fn is_terminated(&self) -> bool {
(**self).is_terminated()
}
}
impl<S> FusedOrderedStream for Option<S>
where
S: FusedOrderedStream,
{
fn is_terminated(&self) -> bool {
self.as_ref().map_or(true, |s| s.is_terminated())
}
}
#[derive(Clone, Copy, Debug, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub enum PollResult<Ordering, Data> {
Item { data: Data, ordering: Ordering },
NoneBefore,
Terminated,
}
impl<D, T> PollResult<T, D> {
pub fn into_data(self) -> Option<D> {
match self {
Self::Item { data, .. } => Some(data),
_ => None,
}
}
pub fn into_tuple(self) -> Option<(T, D)> {
match self {
Self::Item { data, ordering } => Some((ordering, data)),
_ => None,
}
}
pub fn map_data<R>(self, f: impl FnOnce(D) -> R) -> PollResult<T, R> {
match self {
Self::Item { data, ordering } => PollResult::Item {
data: f(data),
ordering,
},
Self::NoneBefore => PollResult::NoneBefore,
Self::Terminated => PollResult::Terminated,
}
}
}
impl<T, D, E> PollResult<T, Result<D, E>> {
pub fn transpose_result(self) -> Result<PollResult<T, D>, E> {
self.transpose_result_item().map_err(|(_, e)| e)
}
pub fn transpose_result_item(self) -> Result<PollResult<T, D>, (T, E)> {
match self {
Self::Item {
data: Ok(data),
ordering,
} => Ok(PollResult::Item { data, ordering }),
Self::Item {
data: Err(data),
ordering,
} => Err((ordering, data)),
Self::NoneBefore => Ok(PollResult::NoneBefore),
Self::Terminated => Ok(PollResult::Terminated),
}
}
}
pub trait OrderedFuture {
type Ordering: Ord;
type Output;
fn poll_before(
self: Pin<&mut Self>,
cx: &mut Context<'_>,
before: Option<&Self::Ordering>,
) -> Poll<Option<(Self::Ordering, Self::Output)>>;
fn position_hint(&self) -> Option<MaybeBorrowed<'_, Self::Ordering>> {
None
}
}
mod adapters;
pub use adapters::*;
mod join;
pub use join::*;
mod multi;
pub use multi::*;