Skip to main content

flexible_io/
reader.rs

1use crate::stable_with_metadata_of::WithMetadataOf;
2
3use std::{
4    any::Any,
5    io::{BufRead, Read, Seek},
6};
7
8#[cfg(target_os = "windows")]
9use std::os::windows::{
10    fs::FileExt,
11    io::{AsHandle, AsRawHandle, AsRawSocket, AsSocket},
12};
13
14#[cfg(target_family = "unix")]
15use std::os::{
16    fd::{AsFd, AsRawFd},
17    unix::fs::FileExt,
18};
19
20/// A reader, which can dynamically provide IO traits.
21///
22/// The following traits may be optionally dynamically provided:
23///
24/// * [`Seek`]
25/// * [`BufRead`]
26/// * [`Any`]
27///
28/// The struct comes with a number of setter methods. The call to these requires proof to the
29/// compiler that the bound is met, inserting the vtable from the impl instance. Afterward, the
30/// bound is not required by any user. Using the (mutable) getters recombines the vtable with the
31/// underlying value.
32///
33/// Note that the value can not be unsized (`dyn` trait) itself. This may be fixed at a later point
34/// to make the reader suitable for use in embedded. In particular, the double indirection of
35/// instantiating with `R = &mut dyn Read` wouldn't make sense as the setters would not be usable,
36/// their bounds can never be met. And combining traits into a large dyn-trait is redundant as it
37/// trait-impls become part of the static validity requirement again.
38///
39/// ## Usage
40///
41/// ```
42/// # use flexible_io::Reader;
43/// let mut buffer: &[u8] = b"Hello, world!";
44/// let mut reader = Reader::new(&mut buffer);
45/// assert!(reader.as_buf().is_none());
46///
47/// // But slices are buffered readers, let's tell everyone.
48/// reader.set_buf();
49/// assert!(reader.as_buf().is_some());
50///
51/// // Now use the ReadBuf implementation directly
52/// let buffered = reader.as_buf_mut().unwrap();
53/// buffered.consume(7);
54/// assert_eq!(buffered.fill_buf().unwrap(), b"world!");
55/// ```
56pub struct Reader<R: ?Sized> {
57    read: *mut dyn Read,
58    vtable: OptTable,
59    inner: R,
60}
61
62#[derive(Clone, Copy, Default)]
63struct OptTable {
64    seek: Option<*mut dyn Seek>,
65    buf: Option<*mut dyn BufRead>,
66    any: Option<*mut dyn Any>,
67
68    // Unix family traits:
69    #[cfg(target_family = "unix")]
70    file_ext: Option<*mut dyn FileExt>,
71    #[cfg(target_family = "unix")]
72    as_fd: Option<*mut dyn AsFd>,
73    #[cfg(target_family = "unix")]
74    as_raw_fd: Option<*mut dyn AsRawFd>,
75
76    // Windows only traits:
77    #[cfg(target_os = "windows")]
78    file_ext: Option<*mut dyn FileExt>,
79    #[cfg(target_os = "windows")]
80    as_handle: Option<*mut dyn AsHandle>,
81    #[cfg(target_os = "windows")]
82    as_raw_handle: Option<*mut dyn AsRawHandle>,
83    #[cfg(target_os = "windows")]
84    as_socket: Option<*mut dyn AsSocket>,
85    #[cfg(target_os = "windows")]
86    as_raw_socket: Option<*mut dyn AsRawSocket>,
87}
88
89/// A box around a type-erased [`Reader`].
90pub struct ReaderBox<'lt> {
91    inner: Box<dyn Read + 'lt>,
92    vtable: OptTable,
93}
94
95impl<R: Read> Reader<R> {
96    /// Wrap an underlying reader by-value.
97    pub fn new(mut reader: R) -> Self {
98        let read = lifetime_erase_trait_vtable!((&mut reader): '_ as Read);
99
100        Reader {
101            inner: reader,
102            read,
103            vtable: OptTable::default(),
104        }
105    }
106}
107
108impl<R: ?Sized> Reader<R> {
109    /// Provide access to the underlying reader.
110    pub fn get_ref(&self) -> &R {
111        &self.inner
112    }
113
114    /// Provide mutable access to the underlying reader.
115    pub fn get_mut(&mut self) -> &mut R {
116        &mut self.inner
117    }
118
119    /// Get a view equivalent to very-fat mutable reference.
120    ///
121    /// This erases the concrete type `R` which allows consumers that intend to avoid polymorphic
122    /// code that monomorphizes. The mutable reference has all accessors of a mutable reference
123    /// except it doesn't offer access with the underlying reader's type itself.
124    pub fn as_mut(&mut self) -> ReaderMut<'_> {
125        // Copy out all the vtable portions, we need a mutable reference to `self` for the
126        // conversion into a dynamically typed `&mut dyn Read`.
127        let Reader {
128            inner: _,
129            read: _,
130            vtable,
131        } = *self;
132
133        ReaderMut {
134            inner: self.as_read_mut(),
135            vtable,
136        }
137    }
138
139    /// Get an allocated, type-erased very-fat mutable box.
140    ///
141    /// This erases the concrete type `R` which allows consumers that intend to avoid polymorphic
142    /// code that monomorphizes. The mutable reference has all accessors of a mutable reference
143    /// except it doesn't offer access with the underlying reader's type itself.
144    pub fn into_boxed<'lt>(self) -> ReaderBox<'lt>
145    where
146        R: Sized + 'lt,
147    {
148        let Reader {
149            inner,
150            read,
151            vtable,
152        } = self;
153
154        let ptr = Box::into_raw(Box::new(inner));
155        let ptr = WithMetadataOf::with_metadata_of_on_stable(ptr, read);
156        let inner = unsafe { Box::from_raw(ptr) };
157
158        ReaderBox { inner, vtable }
159    }
160}
161
162dyn_setter! {
163    impl<R> Reader<R> = self as that {
164        /// Set the V-Table for [`BufRead`].
165        ///
166        /// After this call, the methods [`Self::as_buf`] and [`Self::as_buf_mut`] will return values.
167        fn set_buf -> BufRead = that.vtable.buf;
168
169        /// Set the V-Table for [`Seek`].
170        ///
171        /// After this call, the methods [`Self::as_seek`] and [`Self::as_seek_mut`] will return values.
172        fn set_seek -> Seek = that.vtable.seek;
173
174        /// Set the V-Table for [`Any`].
175        ///
176        /// After this call, the methods [`Self::as_any`] and [`Self::as_any_mut`] will return values.
177        fn set_any -> Any = that.vtable.any;
178    }
179}
180
181#[cfg(target_family = "unix")]
182dyn_setter! {
183    impl<R> Reader<R> = self as that {
184        /// Set the V-Table for [`FileExt`].
185        ///
186        /// After this call, the methods [`Self::as_file_ext`] will return a value. (This trait only has
187        /// methods with a `&self` receiver).
188        fn set_file_ext -> FileExt = that.vtable.file_ext;
189
190        /// Set the V-Table for [`AsRawFd`].
191        ///
192        /// After this call, the methods [`Self::as_fd`] will return a value. (This trait only has
193        /// methods with a `&self` receiver).
194        fn set_as_fd -> AsFd = that.vtable.as_fd;
195
196        /// Set the V-Table for [`AsRawFd`].
197        ///
198        /// After this call, the methods [`Self::as_raw_fd`] will return a value. (This trait only has
199        /// methods with a `&self` receiver).
200        fn set_as_raw_fd -> AsRawFd = that.vtable.as_raw_fd;
201    }
202}
203
204#[cfg(target_os = "windows")]
205dyn_setter! {
206    impl<R> Reader<R> = self as that {
207        /// Set the V-Table for [`FileExt`].
208        ///
209        /// After this call, the methods [`Self::as_file_ext`] will return a value. (This trait only has
210        /// methods with a `&self` receiver).
211        fn set_file_ext -> FileExt = that.vtable.file_ext;
212
213        /// Set the V-Table for [`AsHandle`].
214        ///
215        /// After this call, the methods [`Self::as_handle`] will return a value. (This trait only has
216        /// methods with a `&self` receiver).
217        fn set_as_handle -> AsHandle = that.vtable.as_handle;
218
219        /// Set the V-Table for [`AsRawHandle`].
220        ///
221        /// After this call, the methods [`Self::as_raw_handle`] will return a value. (This trait only has
222        /// methods with a `&self` receiver).
223        fn set_as_raw_handle -> AsRawHandle = that.vtable.as_raw_handle;
224
225        /// Set the V-Table for [`AsSocket`].
226        ///
227        /// After this call, the methods [`Self::as_socket`] will return a value. (This trait only has
228        /// methods with a `&self` receiver).
229        fn set_as_socket -> AsSocket = that.vtable.as_socket;
230
231        /// Set the V-Table for [`AsRawSocket`].
232        ///
233        /// After this call, the methods [`Self::as_raw_socket`] will return a value. (This trait only has
234        /// methods with a `&self` receiver).
235        fn set_as_raw_socket -> AsRawSocket = that.vtable.as_raw_socket;
236    }
237}
238
239impl<R: ?Sized> Reader<R> {
240    /// Get the inner value as a shared dynamic `Read` reference.
241    ///
242    /// This is not terribly useful but provided for completeness.
243    pub fn as_read(&self) -> &(dyn Read + '_) {
244        let ptr = &self.inner as *const R;
245        let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.read);
246        unsafe { &*local }
247    }
248
249    /// Get the inner value as a mutable dynamic `Read` reference.
250    pub fn as_read_mut(&mut self) -> &mut (dyn Read + '_) {
251        let ptr = &mut self.inner as *mut R;
252        let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.read);
253        unsafe { &mut *local }
254    }
255
256    /// Unwrap the inner value at its original sized type.
257    pub fn into_inner(self) -> R
258    where
259        R: Sized,
260    {
261        self.inner
262    }
263}
264
265dyn_getter! {
266    impl<R> Reader<R> = self as that {
267        unsafe const ptr: &that.inner as *const R;
268        unsafe mut ptr: &mut that.inner as *mut R;
269    } {
270        /// Get the inner value as a dynamic `BufRead` reference.
271        ///
272        /// This returns `None` unless a previous call to [`Self::set_buf`] as executed, by any other caller.
273        /// The value can be moved after such call arbitrarily.
274        fn as_buf {
275            /// Get the inner value as a mutable dynamic `BufRead` reference.
276            ///
277            /// This returns `None` unless a previous call to [`Self::set_buf`] as executed, by any other caller.
278            /// The value can be moved after such call arbitrarily.
279            mut: fn as_buf_mut
280        } -> BufRead = that.vtable.buf;
281
282        /// Get the inner value as a dynamic `Seek` reference.
283        ///
284        /// This returns `None` unless a previous call to [`Self::set_seek`] as executed, by any other caller.
285        /// The value can be moved after such call arbitrarily.
286        fn as_seek {
287            /// Get the inner value as a mutable dynamic `Seek` reference.
288            ///
289            /// This returns `None` unless a previous call to [`Self::set_seek`] as executed, by any other caller.
290            /// The value can be moved after such call arbitrarily.
291            mut: fn as_seek_mut
292        } -> Seek = that.vtable.seek;
293
294        /// Get the inner value as a dynamic `Any` reference.
295        fn as_any {
296            /// Get the inner value as a dynamic `Any` reference.
297            mut: fn as_any_mut
298        } -> Any = that.vtable.any;
299    }
300}
301
302#[cfg(target_family = "unix")]
303dyn_getter! {
304    impl<R> Reader<R> = self as that {
305        unsafe const ptr: &that.inner as *const R;
306        unsafe mut ptr: &mut that.inner as *mut R;
307    } {
308        /// Get the inner value as a dynamic [`FileExt`] reference.
309        fn as_file_ext -> FileExt = that.vtable.file_ext;
310
311        /// Get the inner value as a dynamic [`AsFd`] reference.
312        fn as_fd -> AsFd = that.vtable.as_fd;
313
314        /// Get the inner value as a dynamic [`AsRawFd`] reference.
315        fn as_raw_fd -> AsRawFd = that.vtable.as_raw_fd;
316    }
317}
318
319#[cfg(target_os = "windows")]
320dyn_getter! {
321    impl<R> Reader<R> = self as that {
322        unsafe const ptr: &that.inner as *const R;
323        unsafe mut ptr: &mut that.inner as *mut R;
324    } {
325        /// Get the inner value as a dynamic [`FileExt`] reference.
326        ///
327        /// Some of the methods exposed by that trait allow writing to the file.
328        fn as_file_ext -> FileExt = that.vtable.file_ext;
329
330        /// Get the inner value as a dynamic [`AsHandle`] reference.
331        fn as_handle -> AsHandle = that.vtable.as_handle;
332
333        /// Get the inner value as a dynamic [`AsRawHandle`] reference.
334        fn as_raw_handle -> AsRawHandle = that.vtable.as_raw_handle;
335
336        /// Get the inner value as a dynamic [`AsSocket`] reference.
337        fn as_socket -> AsSocket = that.vtable.as_socket;
338
339        /// Get the inner value as a dynamic [`AsRawSocket`] reference.
340        fn as_raw_socket -> AsRawSocket = that.vtable.as_raw_socket;
341    }
342}
343
344impl<R: Read> Read for Reader<R> {
345    fn read(&mut self, buf: &mut [u8]) -> std::io::Result<usize> {
346        self.inner.read(buf)
347    }
348
349    fn read_exact(&mut self, buf: &mut [u8]) -> std::io::Result<()> {
350        self.inner.read_exact(buf)
351    }
352
353    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> std::io::Result<usize> {
354        self.inner.read_to_end(buf)
355    }
356
357    fn read_to_string(&mut self, buf: &mut String) -> std::io::Result<usize> {
358        self.inner.read_to_string(buf)
359    }
360}
361
362/// A mutable reference to a [`Reader`].
363///
364/// This type acts similar to a *very* fat mutable reference. It can be obtained by constructing a
365/// concrete reader type and calling [`Reader::as_mut`].
366///
367/// Note: Any mutable reference to a `Reader` implements `Into<ReaderMut>` for its lifetime. Use
368/// this instead of coercion which would be available if this was a builtin kind of reference.
369///
370/// Note: Any `Reader` implements `Into<ReaderBox>`, which can again be converted to [`ReaderMut`].
371/// Use it for owning a writer without its specific type similar to `Box<dyn Write>`.
372pub struct ReaderMut<'lt> {
373    inner: &'lt mut dyn Read,
374    vtable: OptTable,
375}
376
377impl ReaderMut<'_> {
378    /// Get the inner value as a mutable dynamic `Read` reference.
379    pub fn as_read_mut(&mut self) -> &mut (dyn Read + '_) {
380        &mut *self.inner
381    }
382}
383
384dyn_getter! {
385    impl ReaderMut<'_> = self as that {
386        unsafe const ptr: that.inner as *const dyn Read;
387        unsafe mut ptr: that.inner as *mut dyn Read;
388    } {
389        /// Get the inner value as a dynamic `BufRead` reference.
390        ///
391        /// This returns `None` unless a previous call to [`Reader::set_buf`] as executed, by any other caller.
392        /// The value can be moved after such call arbitrarily.
393        fn as_buf {
394            /// Get the inner value as a mutable dynamic `BufRead` reference.
395            ///
396            /// This returns `None` unless a previous call to [`Reader::set_buf`] as executed, by any other caller.
397            /// The value can be moved after such call arbitrarily.
398            mut: fn as_buf_mut
399        } -> BufRead = that.vtable.buf;
400
401        /// Get the inner value as a dynamic `Seek` reference.
402        ///
403        /// This returns `None` unless a previous call to [`Reader::set_seek`] as executed, by any other caller.
404        /// The value can be moved after such call arbitrarily.
405        fn as_seek {
406            /// Get the inner value as a mutable dynamic `Seek` reference.
407            ///
408            /// This returns `None` unless a previous call to [`Reader::set_seek`] as executed, by any other caller.
409            /// The value can be moved after such call arbitrarily.
410            mut: fn as_seek_mut
411        } -> Seek = that.vtable.seek;
412
413        /// Get the inner value as a dynamic `Any` reference.
414        fn as_any {
415            /// Get the inner value as a dynamic `Any` reference.
416            mut: fn as_any_mut
417        } -> Any = that.vtable.any;
418    }
419}
420
421#[cfg(target_family = "unix")]
422dyn_getter! {
423    impl ReaderMut<'_> = self as that {
424        unsafe const ptr: that.inner as *const dyn Read;
425        unsafe mut ptr: that.inner as *mut dyn Read;
426    } {
427        /// Get the inner value as a dynamic [`FileExt`] reference.
428        fn as_file_ext -> FileExt = that.vtable.file_ext;
429
430        /// Get the inner value as a dynamic [`AsFd`] reference.
431        fn as_fd -> AsFd = that.vtable.as_fd;
432
433        /// Get the inner value as a dynamic [`AsRawFd`] reference.
434        fn as_raw_fd -> AsRawFd = that.vtable.as_raw_fd;
435    }
436}
437
438#[cfg(target_os = "windows")]
439dyn_getter! {
440    impl ReaderMut<'_> = self as that {
441        unsafe const ptr: &that.inner as *const dyn Read;
442        unsafe mut ptr: &mut that.inner as *mut dyn Read;
443    } {
444        /// Get the inner value as a dynamic [`FileExt`] reference.
445        fn as_file_ext -> FileExt = that.vtable.file_ext;
446
447        /// Get the inner value as a dynamic [`AsHandle`] reference.
448        fn as_handle -> AsHandle = that.vtable.as_handle;
449
450        /// Get the inner value as a dynamic [`AsRawHandle`] reference.
451        fn as_raw_handle -> AsRawHandle = that.vtable.as_raw_handle;
452
453        /// Get the inner value as a dynamic [`AsSocket`] reference.
454        fn as_socket -> AsSocket = that.vtable.as_socket;
455
456        /// Get the inner value as a dynamic [`AsRawSocket`] reference.
457        fn as_raw_socket -> AsRawSocket = that.vtable.as_raw_socket;
458    }
459}
460
461impl ReaderBox<'_> {
462    /// Get the inner value as a shared dynamic `Read` reference.
463    ///
464    /// This is not terribly useful but provided for completeness.
465    pub fn as_mut(&mut self) -> ReaderMut<'_> {
466        ReaderMut {
467            vtable: self.vtable,
468            inner: self.as_read_mut(),
469        }
470    }
471
472    /// Get the inner value as a mutable dynamic `Read` reference.
473    pub fn as_read_mut(&mut self) -> &mut (dyn Read + '_) {
474        &mut *self.inner
475    }
476}
477
478dyn_getter! {
479    impl ReaderBox<'_> = self as that {
480        unsafe const ptr: that.inner.as_ref() as *const dyn Read;
481        unsafe mut ptr: that.inner.as_mut() as *mut dyn Read;
482    } {
483        /// Get the inner value as a dynamic `BufRead` reference.
484        ///
485        /// This returns `None` unless a previous call to [`Reader::set_buf`] as executed, by any other caller.
486        /// The value can be moved after such call arbitrarily.
487        fn as_buf {
488            /// Get the inner value as a mutable dynamic `BufRead` reference.
489            ///
490            /// This returns `None` unless a previous call to [`Reader::set_buf`] as executed, by any other caller.
491            /// The value can be moved after such call arbitrarily.
492            mut: fn as_buf_mut
493        } -> BufRead = that.vtable.buf;
494
495        /// Get the inner value as a dynamic `Seek` reference.
496        ///
497        /// This returns `None` unless a previous call to [`Reader::set_seek`] as executed, by any other caller.
498        /// The value can be moved after such call arbitrarily.
499        fn as_seek {
500            /// Get the inner value as a mutable dynamic `Seek` reference.
501            ///
502            /// This returns `None` unless a previous call to [`Reader::set_seek`] as executed, by any other caller.
503            /// The value can be moved after such call arbitrarily.
504            mut: fn as_seek_mut
505        } -> Seek = that.vtable.seek;
506
507        /// Get the inner value as a dynamic `Any` reference.
508        fn as_any {
509            /// Get the inner value as a dynamic `Any` reference.
510            mut: fn as_any_mut
511        } -> Any = that.vtable.any;
512    }
513}
514
515#[cfg(target_family = "unix")]
516dyn_getter! {
517    impl ReaderBox<'_> = self as that {
518        unsafe const ptr: that.inner.as_ref() as *const _;
519        unsafe mut ptr: that.inner.as_mut() as *mut _;
520    } {
521        /// Get the inner value as a dynamic [`FileExt`] reference.
522        fn as_file_ext -> FileExt = that.vtable.file_ext;
523
524        /// Get the inner value as a dynamic [`AsFd`] reference.
525        fn as_fd -> AsFd = that.vtable.as_fd;
526
527        /// Get the inner value as a dynamic [`AsRawFd`] reference.
528        fn as_raw_fd -> AsRawFd = that.vtable.as_raw_fd;
529    }
530}
531
532#[cfg(target_os = "windows")]
533dyn_getter! {
534    impl ReaderBox<'_> = self as that {
535        unsafe const ptr: that.inner.as_ref() as *const dyn Read;
536        unsafe mut ptr: that.inner.as_mut() as *mut dyn Read;
537    } {
538        /// Get the inner value as a dynamic [`FileExt`] reference.
539        fn as_file_ext -> FileExt = that.vtable.file_ext;
540
541        /// Get the inner value as a dynamic [`AsHandle`] reference.
542        fn as_handle -> AsHandle = that.vtable.as_handle;
543
544        /// Get the inner value as a dynamic [`AsRawHandle`] reference.
545        fn as_raw_handle -> AsRawHandle = that.vtable.as_raw_handle;
546
547        /// Get the inner value as a dynamic [`AsSocket`] reference.
548        fn as_socket -> AsSocket = that.vtable.as_socket;
549
550        /// Get the inner value as a dynamic [`AsRawSocket`] reference.
551        fn as_raw_socket -> AsRawSocket = that.vtable.as_raw_socket;
552    }
553}
554
555impl<'lt, R> From<&'lt mut Reader<R>> for ReaderMut<'lt> {
556    fn from(value: &'lt mut Reader<R>) -> Self {
557        value.as_mut()
558    }
559}
560
561impl<'lt, R: 'lt> From<Reader<R>> for ReaderBox<'lt> {
562    fn from(value: Reader<R>) -> Self {
563        value.into_boxed()
564    }
565}
566
567impl<'lt> From<&'lt mut ReaderBox<'_>> for ReaderMut<'lt> {
568    fn from(value: &'lt mut ReaderBox<'_>) -> Self {
569        value.as_mut()
570    }
571}