1extern crate std;
2
3use core::{
4 pin::Pin,
5 task::{Context, Poll},
6};
7
8use extend_pinned::ExtendPinned;
9#[cfg(feature = "sink")]
10use futures_sink::Sink;
11use futures_util::{Stream, stream::FusedStream};
12use pin_project::pin_project;
13#[cfg(feature = "route-sink")]
14use route_sink::{FlushRoute, ReadyRoute, ReadySome};
15
16use crate::{Extending, ExtendingExt};
17
18pub enum ExtendItem<K, T> {
19 Pushed(K),
20 Item(T),
21}
22
23impl<K, T, E> ExtendItem<K, Result<T, E>> {
24 pub fn transpose(self) -> Result<ExtendItem<K, T>, E> {
25 match self {
26 Self::Pushed(x) => Ok(ExtendItem::Pushed(x)),
27 Self::Item(Ok(x)) => Ok(ExtendItem::Item(x)),
28 Self::Item(Err(x)) => Err(x),
29 }
30 }
31}
32
33#[pin_project]
34#[derive(Debug)]
35pub struct ExtendKeyed<S, K> {
36 #[pin]
37 inner: S,
38 pushed: std::collections::VecDeque<K>,
39}
40
41impl<S: Default, K> Default for ExtendKeyed<S, K> {
42 fn default() -> Self {
43 S::default().into()
44 }
45}
46
47impl<S, K> From<S> for ExtendKeyed<S, K> {
48 fn from(inner: S) -> Self {
49 Self {
50 inner,
51 pushed: Default::default(),
52 }
53 }
54}
55
56impl<S: ExtendPinned<T>, K, T> ExtendPinned<(K, T)> for ExtendKeyed<S, K> {
57 fn extend_pinned<I: IntoIterator<Item = (K, T)>>(self: Pin<&mut Self>, iter: I) {
58 let this = self.project();
59 this.inner.extend_pinned(iter.into_iter().map(|(k, t)| {
60 this.pushed.push_back(k);
61 t
62 }));
63 }
64}
65
66impl<S: Stream, K> Stream for ExtendKeyed<S, K> {
67 type Item = ExtendItem<K, S::Item>;
68
69 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
70 let this = self.project();
71 if let Some(k) = this.pushed.pop_front() {
72 return Poll::Ready(Some(ExtendItem::Pushed(k)));
73 }
74 this.inner.poll_next(cx).map(|o| o.map(ExtendItem::Item))
75 }
76}
77
78impl<S: FusedStream, K> FusedStream for ExtendKeyed<S, K> {
79 fn is_terminated(&self) -> bool {
80 self.pushed.is_empty() && self.inner.is_terminated()
81 }
82}
83
84#[cfg(feature = "sink")]
85impl<Item, S: Sink<Item>, K> Sink<Item> for ExtendKeyed<S, K> {
86 type Error = S::Error;
87
88 fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
89 self.project().inner.poll_ready(cx)
90 }
91
92 fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
93 self.project().inner.start_send(item)
94 }
95
96 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
97 self.project().inner.poll_flush(cx)
98 }
99
100 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
101 self.project().inner.poll_close(cx)
102 }
103}
104
105#[cfg(feature = "route-sink")]
106impl<Route, Msg, S: FlushRoute<Route, Msg>, K> FlushRoute<Route, Msg> for ExtendKeyed<S, K> {
107 fn poll_flush_route(
108 self: Pin<&mut Self>,
109 route: &Route,
110 cx: &mut Context<'_>,
111 ) -> Poll<Result<(), Self::Error>> {
112 self.project().inner.poll_flush_route(route, cx)
113 }
114
115 fn poll_close_route(
116 self: Pin<&mut Self>,
117 route: &Route,
118 cx: &mut Context<'_>,
119 ) -> Poll<Result<(), Self::Error>> {
120 self.project().inner.poll_close_route(route, cx)
121 }
122}
123
124#[cfg(feature = "route-sink")]
125impl<Route, Msg, S: ReadyRoute<Route, Msg>, K> ReadyRoute<Route, Msg> for ExtendKeyed<S, K> {
126 fn poll_ready_route(
127 self: Pin<&mut Self>,
128 route: &Route,
129 cx: &mut Context<'_>,
130 ) -> Poll<Result<(), Self::Error>> {
131 self.project().inner.poll_ready_route(route, cx)
132 }
133}
134
135#[cfg(feature = "route-sink")]
136impl<Route, Msg, S: ReadySome<Route, Msg>, K> ReadySome<Route, Msg> for ExtendKeyed<S, K> {
137 fn poll_ready_some(
138 self: Pin<&mut Self>,
139 cx: &mut Context<'_>,
140 ) -> Poll<Result<Route, Self::Error>> {
141 self.project().inner.poll_ready_some(cx)
142 }
143}
144
145pub trait ExtendingKeyedExt: Sized + Stream<Item = (Self::K, Self::T)> {
146 type K;
147 type T;
148
149 #[must_use]
150 fn extending_keyed<S: ExtendPinned<Self::T>>(
151 self,
152 inner: S,
153 ) -> Extending<ExtendKeyed<S, Self::K>, Self> {
154 self.extending(inner.into())
155 }
156
157 #[must_use]
158 fn extending_keyed_default<S: Default + ExtendPinned<Self::T>>(
159 self,
160 ) -> Extending<ExtendKeyed<S, Self::K>, Self> {
161 self.extending_default()
162 }
163}