1#![no_std]
6#![cfg_attr(docsrs, feature(doc_auto_cfg))]
7#![cfg_attr(docsrs, feature(doc_cfg_hide))]
8#![cfg_attr(docsrs, doc(cfg_hide(doc)))]
9
10use core::pin::Pin;
11#[cfg(any(feature = "futures-core", feature = "futures-sink"))]
12use core::task::{Context, Poll};
13
14#[cfg(feature = "futures-core")]
15use futures_core::{FusedFuture, FusedStream, Future, Stream};
16#[cfg(feature = "futures-sink")]
17use futures_sink::Sink;
18use pin_project::pin_project;
19#[cfg(feature = "route-sink")]
20use route_sink::{FlushRoute, ReadyRoute, ReadySome};
21
22#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
24#[pin_project]
25pub struct WithExtra<T, Ex> {
26 #[pin]
27 inner: T,
28 extra: Ex,
29}
30
31impl<T, Ex> WithExtra<T, Ex> {
32 #[must_use]
34 pub const fn new(inner: T, extra: Ex) -> Self {
35 Self { inner, extra }
36 }
37
38 #[must_use]
40 pub fn into_inner(self) -> (T, Ex) {
41 (self.inner, self.extra)
42 }
43
44 #[must_use]
46 pub fn as_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T> {
47 self.project().inner
48 }
49}
50
51impl<T, Ex> From<(T, Ex)> for WithExtra<T, Ex> {
52 fn from((inner, extra): (T, Ex)) -> Self {
53 Self::new(inner, extra)
54 }
55}
56
57impl<T, Ex> From<WithExtra<T, Ex>> for (T, Ex) {
58 fn from(value: WithExtra<T, Ex>) -> Self {
59 value.into_inner()
60 }
61}
62
63impl<T, Ex: Default> From<T> for WithExtra<T, Ex> {
64 fn from(inner: T) -> Self {
65 Self::new(inner, Ex::default())
66 }
67}
68
69impl<T, Ex> AsRef<T> for WithExtra<T, Ex> {
70 fn as_ref(&self) -> &T {
71 &self.inner
72 }
73}
74
75impl<T, Ex> AsMut<T> for WithExtra<T, Ex> {
76 fn as_mut(&mut self) -> &mut T {
77 &mut self.inner
78 }
79}
80
81#[cfg(feature = "futures-core")]
82impl<T: Future, Ex> Future for WithExtra<T, Ex> {
83 type Output = T::Output;
84
85 fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
86 self.project().inner.poll(cx)
87 }
88}
89
90#[cfg(feature = "futures-core")]
91impl<T: FusedFuture, Ex> FusedFuture for WithExtra<T, Ex> {
92 fn is_terminated(&self) -> bool {
93 self.inner.is_terminated()
94 }
95}
96
97#[cfg(feature = "futures-core")]
98impl<T: Stream, Ex> Stream for WithExtra<T, Ex> {
99 type Item = T::Item;
100
101 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
102 self.project().inner.poll_next(cx)
103 }
104}
105
106#[cfg(feature = "futures-core")]
107impl<T: FusedStream, Ex> FusedStream for WithExtra<T, Ex> {
108 fn is_terminated(&self) -> bool {
109 self.inner.is_terminated()
110 }
111}
112
113#[cfg(feature = "futures-sink")]
114impl<Item, T: Sink<Item>, Ex> Sink<Item> for WithExtra<T, Ex> {
115 type Error = T::Error;
116
117 fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
118 self.project().inner.poll_ready(cx)
119 }
120
121 fn start_send(self: Pin<&mut Self>, item: Item) -> Result<(), Self::Error> {
122 self.project().inner.start_send(item)
123 }
124
125 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
126 self.project().inner.poll_flush(cx)
127 }
128
129 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
130 self.project().inner.poll_close(cx)
131 }
132}
133
134#[cfg(feature = "route-sink")]
135impl<Route, Msg, T: FlushRoute<Route, Msg>, Ex> FlushRoute<Route, Msg> for WithExtra<T, Ex> {
136 fn poll_flush_route(
137 self: Pin<&mut Self>,
138 route: &Route,
139 cx: &mut Context<'_>,
140 ) -> Poll<Result<(), Self::Error>> {
141 self.project().inner.poll_flush_route(route, cx)
142 }
143
144 fn poll_close_route(
145 self: Pin<&mut Self>,
146 route: &Route,
147 cx: &mut Context<'_>,
148 ) -> Poll<Result<(), Self::Error>> {
149 self.project().inner.poll_close_route(route, cx)
150 }
151}
152
153#[cfg(feature = "route-sink")]
154impl<Route, Msg, T: ReadyRoute<Route, Msg>, Ex> ReadyRoute<Route, Msg> for WithExtra<T, Ex> {
155 fn poll_ready_route(
156 self: Pin<&mut Self>,
157 route: &Route,
158 cx: &mut Context<'_>,
159 ) -> Poll<Result<(), Self::Error>> {
160 self.project().inner.poll_ready_route(route, cx)
161 }
162}
163
164#[cfg(feature = "route-sink")]
165impl<Route, Msg, T: ReadySome<Route, Msg>, Ex> ReadySome<Route, Msg> for WithExtra<T, Ex> {
166 fn poll_ready_some(
167 self: Pin<&mut Self>,
168 cx: &mut Context<'_>,
169 ) -> Poll<Result<Route, Self::Error>> {
170 self.project().inner.poll_ready_some(cx)
171 }
172}