1use pin_project_lite::pin_project;
2use std::io::{IoSlice, Result};
3use std::pin::Pin;
4use std::task::{ready, Context, Poll};
5
6use tokio::io::{AsyncRead, AsyncWrite, ReadBuf};
7
8pin_project! {
9 pub struct InspectReader<R, F> {
13 #[pin]
14 reader: R,
15 f: F,
16 }
17}
18
19impl<R, F> InspectReader<R, F> {
20 pub fn new(reader: R, f: F) -> InspectReader<R, F>
27 where
28 R: AsyncRead,
29 F: FnMut(&[u8]),
30 {
31 InspectReader { reader, f }
32 }
33
34 pub fn get_ref(&self) -> &R {
36 &self.reader
37 }
38
39 pub fn get_mut(&mut self) -> &mut R {
43 &mut self.reader
44 }
45
46 pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut R> {
50 self.project().reader
51 }
52
53 pub fn into_inner(self) -> R {
55 self.reader
56 }
57}
58
59impl<R: AsyncRead, F: FnMut(&[u8])> AsyncRead for InspectReader<R, F> {
60 fn poll_read(
61 self: Pin<&mut Self>,
62 cx: &mut Context<'_>,
63 buf: &mut ReadBuf<'_>,
64 ) -> Poll<Result<()>> {
65 let me = self.project();
66 let filled_length = buf.filled().len();
67 ready!(me.reader.poll_read(cx, buf))?;
68 (me.f)(&buf.filled()[filled_length..]);
69 Poll::Ready(Ok(()))
70 }
71}
72
73impl<R: AsyncWrite, F> AsyncWrite for InspectReader<R, F> {
74 fn poll_write(
75 self: Pin<&mut Self>,
76 cx: &mut Context<'_>,
77 buf: &[u8],
78 ) -> Poll<std::result::Result<usize, std::io::Error>> {
79 self.project().reader.poll_write(cx, buf)
80 }
81
82 fn poll_flush(
83 self: Pin<&mut Self>,
84 cx: &mut Context<'_>,
85 ) -> Poll<std::result::Result<(), std::io::Error>> {
86 self.project().reader.poll_flush(cx)
87 }
88
89 fn poll_shutdown(
90 self: Pin<&mut Self>,
91 cx: &mut Context<'_>,
92 ) -> Poll<std::result::Result<(), std::io::Error>> {
93 self.project().reader.poll_shutdown(cx)
94 }
95
96 fn poll_write_vectored(
97 self: Pin<&mut Self>,
98 cx: &mut Context<'_>,
99 bufs: &[IoSlice<'_>],
100 ) -> Poll<Result<usize>> {
101 self.project().reader.poll_write_vectored(cx, bufs)
102 }
103
104 fn is_write_vectored(&self) -> bool {
105 self.reader.is_write_vectored()
106 }
107}
108
109pin_project! {
110 pub struct InspectWriter<W, F> {
114 #[pin]
115 writer: W,
116 f: F,
117 }
118}
119
120impl<W, F> InspectWriter<W, F> {
121 pub fn new(writer: W, f: F) -> InspectWriter<W, F>
128 where
129 W: AsyncWrite,
130 F: FnMut(&[u8]),
131 {
132 InspectWriter { writer, f }
133 }
134
135 pub fn get_ref(&self) -> &W {
137 &self.writer
138 }
139
140 pub fn get_mut(&mut self) -> &mut W {
144 &mut self.writer
145 }
146
147 pub fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut W> {
151 self.project().writer
152 }
153
154 pub fn into_inner(self) -> W {
156 self.writer
157 }
158}
159
160impl<W: AsyncWrite, F: FnMut(&[u8])> AsyncWrite for InspectWriter<W, F> {
161 fn poll_write(self: Pin<&mut Self>, cx: &mut Context<'_>, buf: &[u8]) -> Poll<Result<usize>> {
162 let me = self.project();
163 let res = me.writer.poll_write(cx, buf);
164 if let Poll::Ready(Ok(count)) = res {
165 if count != 0 {
166 (me.f)(&buf[..count]);
167 }
168 }
169 res
170 }
171
172 fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
173 let me = self.project();
174 me.writer.poll_flush(cx)
175 }
176
177 fn poll_shutdown(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Result<()>> {
178 let me = self.project();
179 me.writer.poll_shutdown(cx)
180 }
181
182 fn poll_write_vectored(
183 self: Pin<&mut Self>,
184 cx: &mut Context<'_>,
185 bufs: &[IoSlice<'_>],
186 ) -> Poll<Result<usize>> {
187 let me = self.project();
188 let res = me.writer.poll_write_vectored(cx, bufs);
189 if let Poll::Ready(Ok(mut count)) = res {
190 for buf in bufs {
191 if count == 0 {
192 break;
193 }
194 let size = count.min(buf.len());
195 if size != 0 {
196 (me.f)(&buf[..size]);
197 count -= size;
198 }
199 }
200 }
201 res
202 }
203
204 fn is_write_vectored(&self) -> bool {
205 self.writer.is_write_vectored()
206 }
207}
208
209impl<W: AsyncRead, F> AsyncRead for InspectWriter<W, F> {
210 fn poll_read(
211 self: Pin<&mut Self>,
212 cx: &mut Context<'_>,
213 buf: &mut ReadBuf<'_>,
214 ) -> Poll<std::io::Result<()>> {
215 self.project().writer.poll_read(cx, buf)
216 }
217}