hypershell_tokio_components/providers/
stream.rs1use core::convert::Infallible;
2use core::iter::Once;
3use core::marker::PhantomData;
4
5use cgp::extra::handler::{Handler, HandlerComponent};
6use cgp::prelude::*;
7use futures::AsyncRead as FuturesAsyncRead;
8use futures::io::Cursor;
9use futures::stream::Iter;
10use tokio::io::{AsyncRead as TokioAsyncRead, AsyncReadExt as _};
11use tokio_util::compat::{Compat, FuturesAsyncReadCompatExt, TokioAsyncReadCompatExt};
12use tokio_util::io::ReaderStream;
13
14use crate::types::{FuturesAsyncReadStream, FuturesStream, TokioAsyncReadStream};
15
16#[cgp_new_provider]
17impl<Context, Code, Input> Handler<Context, Code, Input> for HandleTokioAsyncReadToBytes
18where
19 Context: CanRaiseAsyncError<std::io::Error>,
20 Input: Send + TokioAsyncRead + Unpin,
21 Code: Send,
22{
23 type Output = Vec<u8>;
24
25 async fn handle(
26 _context: &Context,
27 _tag: PhantomData<Code>,
28 mut input: Input,
29 ) -> Result<Vec<u8>, Context::Error> {
30 let mut output = Vec::new();
31
32 input
33 .read_to_end(&mut output)
34 .await
35 .map_err(Context::raise_error)?;
36
37 Ok(output)
38 }
39}
40
41#[cgp_new_provider]
42impl<Context, Code, Input> Handler<Context, Code, Input> for HandleTokioAsyncReadToString
43where
44 Context: CanRaiseAsyncError<std::io::Error>,
45 Input: Send + TokioAsyncRead + Unpin,
46 Code: Send,
47{
48 type Output = String;
49
50 async fn handle(
51 _context: &Context,
52 _tag: PhantomData<Code>,
53 mut input: Input,
54 ) -> Result<String, Context::Error> {
55 let mut output = String::new();
56
57 input
58 .read_to_string(&mut output)
59 .await
60 .map_err(Context::raise_error)?;
61
62 Ok(output)
63 }
64}
65
66#[cgp_new_provider]
67impl<Context, Code, Input> Handler<Context, Code, Input> for HandleBytesToTokioAsyncRead
68where
69 Context: CanRaiseAsyncError<std::io::Error>,
70 Input: Send + AsRef<[u8]> + Unpin,
71 Code: Send,
72{
73 type Output = TokioAsyncReadStream<Compat<Cursor<Input>>>;
74
75 async fn handle(
76 _context: &Context,
77 _tag: PhantomData<Code>,
78 input: Input,
79 ) -> Result<TokioAsyncReadStream<Compat<Cursor<Input>>>, Context::Error> {
80 Ok(Cursor::new(input).compat().into())
81 }
82}
83
84#[cgp_new_provider]
85impl<Context, Code, Input> Handler<Context, Code, Input> for HandleBytesToStream
86where
87 Context: CanRaiseAsyncError<std::io::Error>,
88 Input: Send + AsRef<[u8]> + Unpin,
89 Code: Send,
90{
91 type Output = FuturesStream<Iter<Once<Result<Input, Infallible>>>>;
92
93 async fn handle(
94 _context: &Context,
95 _tag: PhantomData<Code>,
96 input: Input,
97 ) -> Result<Self::Output, Context::Error> {
98 Ok(futures::stream::iter(core::iter::once(Ok(input))).into())
99 }
100}
101
102#[cgp_new_provider]
103impl<Context, Code, Input> Handler<Context, Code, Input> for FuturesToTokioAsyncRead
104where
105 Context: HasAsyncErrorType,
106 Input: Send + FuturesAsyncRead + Unpin,
107 Code: Send,
108{
109 type Output = TokioAsyncReadStream<Compat<Input>>;
110
111 async fn handle(
112 _context: &Context,
113 _tag: PhantomData<Code>,
114 input: Input,
115 ) -> Result<TokioAsyncReadStream<Compat<Input>>, Context::Error> {
116 Ok(input.compat().into())
117 }
118}
119
120#[cgp_new_provider]
121impl<Context, Code, Input> Handler<Context, Code, Input> for TokioToFuturesAsyncRead
122where
123 Context: HasAsyncErrorType,
124 Input: Send + TokioAsyncRead + Unpin,
125 Code: Send,
126{
127 type Output = FuturesAsyncReadStream<Compat<Input>>;
128
129 async fn handle(
130 _context: &Context,
131 _tag: PhantomData<Code>,
132 input: Input,
133 ) -> Result<FuturesAsyncReadStream<Compat<Input>>, Context::Error> {
134 Ok(input.compat().into())
135 }
136}
137
138#[cgp_new_provider]
139impl<Context, Code, Input> Handler<Context, Code, Input> for WrapTokioAsyncRead
140where
141 Context: HasAsyncErrorType,
142 Input: Send + TokioAsyncRead + Unpin,
143 Code: Send,
144{
145 type Output = TokioAsyncReadStream<Input>;
146
147 async fn handle(
148 _context: &Context,
149 _tag: PhantomData<Code>,
150 input: Input,
151 ) -> Result<TokioAsyncReadStream<Input>, Context::Error> {
152 Ok(input.into())
153 }
154}
155
156#[cgp_new_provider]
157impl<Context, Code, Input> Handler<Context, Code, Input> for WrapFuturesAsyncRead
158where
159 Context: HasAsyncErrorType,
160 Input: Send + FuturesAsyncRead + Unpin,
161 Code: Send,
162{
163 type Output = FuturesAsyncReadStream<Input>;
164
165 async fn handle(
166 _context: &Context,
167 _tag: PhantomData<Code>,
168 input: Input,
169 ) -> Result<FuturesAsyncReadStream<Input>, Context::Error> {
170 Ok(input.into())
171 }
172}
173
174#[cgp_new_provider]
175impl<Context, Code, Input> Handler<Context, Code, Input> for AsyncReadToStream
176where
177 Context: HasAsyncErrorType,
178 Input: Send + TokioAsyncRead + Unpin,
179 Code: Send,
180{
181 type Output = FuturesStream<ReaderStream<Input>>;
182
183 async fn handle(
184 _context: &Context,
185 _tag: PhantomData<Code>,
186 input: Input,
187 ) -> Result<FuturesStream<ReaderStream<Input>>, Context::Error> {
188 Ok(ReaderStream::new(input).into())
189 }
190}