1use std::{
2 fmt, io,
3 pin::Pin,
4 task::{Context, Poll},
5};
6
7use bitflags::bitflags;
8use bytes::{Buf, BytesMut};
9use futures_core::{ready, Stream};
10use futures_sink::Sink;
11use pin_project_lite::pin_project;
12
13use crate::{AsyncRead, AsyncWrite, Decoder, Encoder};
14
15const LW: usize = 1024;
17const HW: usize = 8 * 1024;
19
20bitflags! {
21 #[derive(Debug, Clone, Copy)]
22 struct Flags: u8 {
23 const EOF = 0b0001;
24 const READABLE = 0b0010;
25 }
26}
27
28pin_project! {
29 pub struct Framed<T, U> {
37 #[pin]
38 io: T,
39 codec: U,
40 flags: Flags,
41 read_buf: BytesMut,
42 write_buf: BytesMut,
43 }
44}
45
46impl<T, U> Framed<T, U> {
47 pub fn new(io: T, codec: U) -> Framed<T, U> {
54 Framed {
55 io,
56 codec,
57 flags: Flags::empty(),
58 read_buf: BytesMut::with_capacity(HW),
59 write_buf: BytesMut::with_capacity(HW),
60 }
61 }
62}
63
64impl<T, U> Framed<T, U> {
65 pub fn codec_ref(&self) -> &U {
67 &self.codec
68 }
69
70 pub fn codec_mut(&mut self) -> &mut U {
72 &mut self.codec
73 }
74
75 pub fn io_ref(&self) -> &T {
80 &self.io
81 }
82
83 pub fn io_mut(&mut self) -> &mut T {
88 &mut self.io
89 }
90
91 pub fn io_pin(self: Pin<&mut Self>) -> Pin<&mut T> {
93 self.project().io
94 }
95
96 pub fn is_read_buf_empty(&self) -> bool {
98 self.read_buf.is_empty()
99 }
100
101 pub fn is_write_buf_empty(&self) -> bool {
103 self.write_buf.is_empty()
104 }
105
106 pub fn is_write_buf_full(&self) -> bool {
108 self.write_buf.len() >= HW
109 }
110
111 pub fn is_write_ready(&self) -> bool {
115 self.write_buf.len() < HW
116 }
117
118 pub fn replace_codec<U2>(self, codec: U2) -> Framed<T, U2> {
120 Framed {
121 codec,
122 io: self.io,
123 flags: self.flags,
124 read_buf: self.read_buf,
125 write_buf: self.write_buf,
126 }
127 }
128
129 pub fn into_map_io<F, T2>(self, f: F) -> Framed<T2, U>
131 where
132 F: Fn(T) -> T2,
133 {
134 Framed {
135 io: f(self.io),
136 codec: self.codec,
137 flags: self.flags,
138 read_buf: self.read_buf,
139 write_buf: self.write_buf,
140 }
141 }
142
143 pub fn into_map_codec<F, U2>(self, f: F) -> Framed<T, U2>
145 where
146 F: Fn(U) -> U2,
147 {
148 Framed {
149 io: self.io,
150 codec: f(self.codec),
151 flags: self.flags,
152 read_buf: self.read_buf,
153 write_buf: self.write_buf,
154 }
155 }
156}
157
158impl<T, U> Framed<T, U> {
159 pub fn write<I>(mut self: Pin<&mut Self>, item: I) -> Result<(), <U as Encoder<I>>::Error>
161 where
162 T: AsyncWrite,
163 U: Encoder<I>,
164 {
165 let this = self.as_mut().project();
166 let remaining = this.write_buf.capacity() - this.write_buf.len();
167 if remaining < LW {
168 this.write_buf.reserve(HW - remaining);
169 }
170
171 this.codec.encode(item, this.write_buf)?;
172 Ok(())
173 }
174
175 pub fn next_item(
177 mut self: Pin<&mut Self>,
178 cx: &mut Context<'_>,
179 ) -> Poll<Option<Result<<U as Decoder>::Item, U::Error>>>
180 where
181 T: AsyncRead,
182 U: Decoder,
183 {
184 loop {
185 let this = self.as_mut().project();
186 if this.flags.contains(Flags::READABLE) {
192 if this.flags.contains(Flags::EOF) {
193 match this.codec.decode_eof(this.read_buf) {
194 Ok(Some(frame)) => return Poll::Ready(Some(Ok(frame))),
195 Ok(None) => return Poll::Ready(None),
196 Err(err) => return Poll::Ready(Some(Err(err))),
197 }
198 }
199
200 tracing::trace!("attempting to decode a frame");
201
202 match this.codec.decode(this.read_buf) {
203 Ok(Some(frame)) => {
204 tracing::trace!("frame decoded from buffer");
205 return Poll::Ready(Some(Ok(frame)));
206 }
207 Err(err) => return Poll::Ready(Some(Err(err))),
208 _ => (), }
210
211 this.flags.remove(Flags::READABLE);
212 }
213
214 debug_assert!(!this.flags.contains(Flags::EOF));
215
216 let remaining = this.read_buf.capacity() - this.read_buf.len();
218 if remaining < LW {
219 this.read_buf.reserve(HW - remaining)
220 }
221
222 let cnt = match tokio_util::io::poll_read_buf(this.io, cx, this.read_buf) {
223 Poll::Pending => return Poll::Pending,
224 Poll::Ready(Err(err)) => return Poll::Ready(Some(Err(err.into()))),
225 Poll::Ready(Ok(cnt)) => cnt,
226 };
227
228 if cnt == 0 {
229 this.flags.insert(Flags::EOF);
230 }
231 this.flags.insert(Flags::READABLE);
232 }
233 }
234
235 pub fn flush<I>(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), U::Error>>
237 where
238 T: AsyncWrite,
239 U: Encoder<I>,
240 {
241 let mut this = self.as_mut().project();
242 tracing::trace!("flushing framed transport");
243
244 while !this.write_buf.is_empty() {
245 tracing::trace!("writing; remaining={}", this.write_buf.len());
246
247 let n = ready!(this.io.as_mut().poll_write(cx, this.write_buf))?;
248
249 if n == 0 {
250 return Poll::Ready(Err(io::Error::new(
251 io::ErrorKind::WriteZero,
252 "failed to write frame to transport",
253 )
254 .into()));
255 }
256
257 this.write_buf.advance(n);
259 }
260
261 ready!(this.io.poll_flush(cx))?;
263
264 tracing::trace!("framed transport flushed");
265 Poll::Ready(Ok(()))
266 }
267
268 pub fn close<I>(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), U::Error>>
270 where
271 T: AsyncWrite,
272 U: Encoder<I>,
273 {
274 let mut this = self.as_mut().project();
275 ready!(this.io.as_mut().poll_flush(cx))?;
276 ready!(this.io.as_mut().poll_shutdown(cx))?;
277 Poll::Ready(Ok(()))
278 }
279}
280
281impl<T, U> Stream for Framed<T, U>
282where
283 T: AsyncRead,
284 U: Decoder,
285{
286 type Item = Result<U::Item, U::Error>;
287
288 fn poll_next(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<Self::Item>> {
289 self.next_item(cx)
290 }
291}
292
293impl<T, U, I> Sink<I> for Framed<T, U>
294where
295 T: AsyncWrite,
296 U: Encoder<I>,
297 U::Error: From<io::Error>,
298{
299 type Error = U::Error;
300
301 fn poll_ready(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
302 if self.is_write_ready() {
303 Poll::Ready(Ok(()))
304 } else {
305 self.flush(cx)
306 }
307 }
308
309 fn start_send(self: Pin<&mut Self>, item: I) -> Result<(), Self::Error> {
310 self.write(item)
311 }
312
313 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
314 self.flush(cx)
315 }
316
317 fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<(), Self::Error>> {
318 self.close(cx)
319 }
320}
321
322impl<T, U> fmt::Debug for Framed<T, U>
323where
324 T: fmt::Debug,
325 U: fmt::Debug,
326{
327 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
328 f.debug_struct("Framed")
329 .field("io", &self.io)
330 .field("codec", &self.codec)
331 .finish()
332 }
333}
334
335impl<T, U> Framed<T, U> {
336 pub fn from_parts(parts: FramedParts<T, U>) -> Framed<T, U> {
343 Framed {
344 io: parts.io,
345 codec: parts.codec,
346 flags: parts.flags,
347 write_buf: parts.write_buf,
348 read_buf: parts.read_buf,
349 }
350 }
351
352 pub fn into_parts(self) -> FramedParts<T, U> {
358 FramedParts {
359 io: self.io,
360 codec: self.codec,
361 flags: self.flags,
362 read_buf: self.read_buf,
363 write_buf: self.write_buf,
364 }
365 }
366}
367
368#[derive(Debug)]
373pub struct FramedParts<T, U> {
374 pub io: T,
376
377 pub codec: U,
379
380 pub read_buf: BytesMut,
382
383 pub write_buf: BytesMut,
385
386 flags: Flags,
387}
388
389impl<T, U> FramedParts<T, U> {
390 pub fn new(io: T, codec: U) -> FramedParts<T, U> {
392 FramedParts {
393 io,
394 codec,
395 flags: Flags::empty(),
396 read_buf: BytesMut::new(),
397 write_buf: BytesMut::new(),
398 }
399 }
400
401 pub fn with_read_buf(io: T, codec: U, read_buf: BytesMut) -> FramedParts<T, U> {
403 FramedParts {
404 io,
405 codec,
406 read_buf,
407 flags: Flags::empty(),
408 write_buf: BytesMut::new(),
409 }
410 }
411}