uninit_read/
assume_uninit_read.rs

1use crate::UninitRead;
2use std::fmt;
3use std::fmt::{Arguments, Debug, Display};
4use std::io::{BufRead, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
5
6/// A wrapper that asserts a reader upholds the `UninitRead` contract.
7///
8/// Use this to wrap a reader from a third-party crate that is known to be
9/// well-behaved (i.e., it doesn't read from the buffer before writing to it)
10/// but does not implement `UninitRead` itself.
11#[repr(transparent)]
12pub struct AssumeUninitRead<R>(R);
13
14impl<R> AssumeUninitRead<R> {
15    /// Wraps a reader, asserting that it adheres to the `UninitRead` contract.
16    ///
17    /// # Safety
18    ///
19    /// By calling this function, the caller guarantees that the `Read` and/or
20    /// `AsyncRead` implementation of `R` will not read from any part of the
21    /// provided buffer that has not been written to by the implementation
22    /// itself within the same call.
23    #[inline]
24    pub const unsafe fn assume_uninit_read(reader: R) -> Self {
25        Self(reader)
26    }
27
28    /// Unwraps this `AssumeUninitRead`, returning the underlying reader.
29    #[inline]
30    pub fn into_inner(self) -> R {
31        self.0
32    }
33}
34
35impl<R> AsRef<R> for AssumeUninitRead<R> {
36    #[inline]
37    fn as_ref(&self) -> &R {
38        &self.0
39    }
40}
41
42impl<R> AsMut<R> for AssumeUninitRead<R> {
43    #[inline]
44    fn as_mut(&mut self) -> &mut R {
45        &mut self.0
46    }
47}
48
49impl<R: Read> Read for AssumeUninitRead<R> {
50    #[inline]
51    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
52        self.0.read(buf)
53    }
54
55    #[inline]
56    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> std::io::Result<usize> {
57        self.0.read_vectored(bufs)
58    }
59
60    #[inline]
61    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
62        self.0.read_to_end(buf)
63    }
64
65    #[inline]
66    fn read_to_string(&mut self, buf: &mut String) -> std::io::Result<usize> {
67        self.0.read_to_string(buf)
68    }
69
70    #[inline]
71    fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> {
72        self.0.read_exact(buf)
73    }
74}
75
76impl<R: BufRead> BufRead for AssumeUninitRead<R> {
77    #[inline]
78    fn fill_buf(&mut self) -> std::io::Result<&[u8]> {
79        self.0.fill_buf()
80    }
81
82    #[inline]
83    fn consume(&mut self, amount: usize) {
84        self.0.consume(amount)
85    }
86
87    #[inline]
88    fn read_until(&mut self, byte: u8, buf: &mut Vec<u8>) -> std::io::Result<usize> {
89        self.0.read_until(byte, buf)
90    }
91
92    #[inline]
93    fn skip_until(&mut self, byte: u8) -> std::io::Result<usize> {
94        self.0.skip_until(byte)
95    }
96
97    #[inline]
98    fn read_line(&mut self, buf: &mut String) -> std::io::Result<usize> {
99        self.0.read_line(buf)
100    }
101}
102
103impl<R: Seek> Seek for AssumeUninitRead<R> {
104    #[inline]
105    fn seek(&mut self, pos: SeekFrom) -> std::io::Result<u64> {
106        self.0.seek(pos)
107    }
108
109    #[inline]
110    fn rewind(&mut self) -> std::io::Result<()> {
111        self.0.rewind()
112    }
113
114    #[inline]
115    fn stream_position(&mut self) -> std::io::Result<u64> {
116        self.0.stream_position()
117    }
118
119    #[inline]
120    fn seek_relative(&mut self, offset: i64) -> std::io::Result<()> {
121        self.0.seek_relative(offset)
122    }
123}
124
125impl<R: Write> Write for AssumeUninitRead<R> {
126    #[inline]
127    fn write(&mut self, buf: &[u8]) -> std::io::Result<usize> {
128        self.0.write(buf)
129    }
130
131    #[inline]
132    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> std::io::Result<usize> {
133        self.0.write_vectored(bufs)
134    }
135
136    #[inline]
137    fn flush(&mut self) -> std::io::Result<()> {
138        self.0.flush()
139    }
140
141    #[inline]
142    fn write_all(&mut self, buf: &[u8]) -> std::io::Result<()> {
143        self.0.write_all(buf)
144    }
145
146    #[inline]
147    fn write_fmt(&mut self, args: Arguments<'_>) -> std::io::Result<()> {
148        self.0.write_fmt(args)
149    }
150}
151
152#[cfg(feature = "async")]
153mod async_wrapper {
154    use crate::AssumeUninitRead;
155    use futures_io::{AsyncBufRead, AsyncRead, AsyncSeek, AsyncWrite};
156    use std::io::{IoSlice, IoSliceMut, SeekFrom};
157    use std::pin::Pin;
158    use std::task::{Context, Poll};
159
160    impl<R> AssumeUninitRead<R> {
161        /// Projects a pinned mutable reference to the inner reader.
162        ///
163        /// # Safety
164        ///
165        /// `AssumeUninitRead` is a transparent wrapper with no drop logic
166        /// or pin projections. Pinning is structural: if the wrapper is pinned,
167        /// the inner `R` is also pinned and never moved.
168        #[inline]
169        fn project_pin(self: Pin<&mut Self>) -> Pin<&mut R> {
170            // SAFETY: See function documentation.
171            unsafe { self.map_unchecked_mut(|s| &mut s.0) }
172        }
173    }
174
175    impl<R: AsyncRead> AsyncRead for AssumeUninitRead<R> {
176        #[inline]
177        fn poll_read(
178            self: Pin<&mut Self>,
179            cx: &mut Context<'_>,
180            buf: &mut [u8],
181        ) -> Poll<std::io::Result<usize>> {
182            self.project_pin().poll_read(cx, buf)
183        }
184
185        #[inline]
186        fn poll_read_vectored(
187            self: Pin<&mut Self>,
188            cx: &mut Context<'_>,
189            bufs: &mut [IoSliceMut<'_>],
190        ) -> Poll<std::io::Result<usize>> {
191            self.project_pin().poll_read_vectored(cx, bufs)
192        }
193    }
194
195    impl<R: AsyncBufRead> AsyncBufRead for AssumeUninitRead<R> {
196        #[inline]
197        fn poll_fill_buf(
198            self: Pin<&mut Self>,
199            cx: &mut Context<'_>,
200        ) -> Poll<std::io::Result<&[u8]>> {
201            self.project_pin().poll_fill_buf(cx)
202        }
203
204        #[inline]
205        fn consume(self: Pin<&mut Self>, amt: usize) {
206            self.project_pin().consume(amt)
207        }
208    }
209
210    impl<R: AsyncSeek> AsyncSeek for AssumeUninitRead<R> {
211        #[inline]
212        fn poll_seek(
213            self: Pin<&mut Self>,
214            cx: &mut Context<'_>,
215            pos: SeekFrom,
216        ) -> Poll<std::io::Result<u64>> {
217            self.project_pin().poll_seek(cx, pos)
218        }
219    }
220
221    impl<R: AsyncWrite> AsyncWrite for AssumeUninitRead<R> {
222        #[inline]
223        fn poll_write(
224            self: Pin<&mut Self>,
225            cx: &mut Context<'_>,
226            buf: &[u8],
227        ) -> Poll<std::io::Result<usize>> {
228            self.project_pin().poll_write(cx, buf)
229        }
230
231        #[inline]
232        fn poll_write_vectored(
233            self: Pin<&mut Self>,
234            cx: &mut Context<'_>,
235            bufs: &[IoSlice<'_>],
236        ) -> Poll<std::io::Result<usize>> {
237            self.project_pin().poll_write_vectored(cx, bufs)
238        }
239
240        #[inline]
241        fn poll_flush(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
242            self.project_pin().poll_flush(cx)
243        }
244
245        #[inline]
246        fn poll_close(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<std::io::Result<()>> {
247            self.project_pin().poll_close(cx)
248        }
249    }
250}
251
252impl<R: Debug> Debug for AssumeUninitRead<R> {
253    #[inline]
254    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
255        f.debug_tuple("AssumeUninitRead").field(&self.0).finish()
256    }
257}
258
259impl<R: Display> Display for AssumeUninitRead<R> {
260    #[inline]
261    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
262        Display::fmt(&self.0, f)
263    }
264}
265
266impl<R: Clone> Clone for AssumeUninitRead<R> {
267    #[inline]
268    fn clone(&self) -> Self {
269        Self(self.0.clone())
270    }
271}
272
273impl<R: Copy> Copy for AssumeUninitRead<R> {}
274
275impl<R: PartialEq> PartialEq for AssumeUninitRead<R> {
276    #[inline]
277    fn eq(&self, other: &Self) -> bool {
278        self.0 == other.0
279    }
280}
281
282impl<R: Eq> Eq for AssumeUninitRead<R> {}
283
284impl<R: PartialOrd> PartialOrd for AssumeUninitRead<R> {
285    #[inline]
286    fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
287        self.0.partial_cmp(&other.0)
288    }
289}
290
291impl<R: Ord> Ord for AssumeUninitRead<R> {
292    #[inline]
293    fn cmp(&self, other: &Self) -> std::cmp::Ordering {
294        self.0.cmp(&other.0)
295    }
296}
297
298impl<R: std::hash::Hash> std::hash::Hash for AssumeUninitRead<R> {
299    #[inline]
300    fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
301        self.0.hash(state);
302    }
303}
304
305// SAFETY: The caller of `AssumeUninitRead::assume_uninit_read` guarantees that the wrapped
306// reader `R` upholds the `UninitRead` contract.
307unsafe impl<R> UninitRead for AssumeUninitRead<R> {}