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}