1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
use std::io::{BufRead, Read, Seek};
use crate::stable_with_metadata_of::WithMetadataOf;

/// A reader, which can dynamically provide IO traits.
///
/// The following traits may be optionally dynamically provided:
///
/// * [`Seek`]
/// * [`BufRead`]
///
/// The struct comes with a number of setter methods. The call to these requires proof to the
/// compiler that the bound is met, inserting the vtable from the impl instance. Afterward, the
/// bound is not required by any user. Using the (mutable) getters recombines the vtable with the
/// underlying value.
///
/// Note that the value can not be unsized (`dyn` trait) itself. This may be fixed at a later point
/// to make the reader suitable for use in embedded. In particular, the double indirection of
/// instantiating with `R = &mut dyn Read` wouldn't make sense as the setters would not be usable,
/// their bounds can never be met. And combining traits into a large dyn-trait is redundant as it
/// trait-impls become part of the static validity requirement again.
///
/// ## Usage
///
/// ```
/// # use flexible_io::Reader;
/// let mut buffer: &[u8] = b"Hello, world!";
/// let mut reader = Reader::new(&mut buffer);
/// assert!(reader.as_buf().is_none());
///
/// // But slices are buffered readers, let's tell everyone.
/// reader.set_buf();
/// assert!(reader.as_buf().is_some());
///
/// // Now use the ReadBuf implementation directly
/// let buffered = reader.as_buf_mut().unwrap();
/// buffered.consume(7);
/// assert_eq!(buffered.fill_buf().unwrap(), b"world!");
/// ```
pub struct Reader<R> {
    inner: R,
    read: *mut dyn Read,
    seek: Option<*mut dyn Seek>,
    buf: Option<*mut dyn BufRead>,
}

/// A mutable reference to a [`Reader`].
///
/// This type acts similar to a *very* fat mutable reference. It can be obtained by constructing a
/// concrete reader type and calling [`Reader::as_mut`].
///
/// Note: Any mutable reference to a `Reader` implements `Into<ReaderMut>` for its lifetime. Use
/// this instead of coercion which would be available if this was a builtin kind of reference.
pub struct ReaderMut<'lt> {
    inner: &'lt mut dyn Read,
    seek: Option<*mut dyn Seek>,
    buf: Option<*mut dyn BufRead>,
}

impl<R: Read> Reader<R> {
    /// Wrap an underlying reader by-value.
    pub fn new(mut reader: R) -> Self {
        let read = lifetime_erase_trait_vtable!((&mut reader): '_ as Read);

        Reader {
            inner: reader,
            read,
            seek: None,
            buf: None,
        }
    }
}

impl<R> Reader<R> {
    /// Provide access to the underlying reader.
    pub fn get_ref(&self) -> &R {
        &self.inner
    }

    /// Provide mutable access to the underlying reader.
    pub fn get_mut(&mut self) -> &mut R {
        &mut self.inner
    }

    /// Get a view equivalent to very-fat mutable reference.
    ///
    /// This erases the concrete type `R` which allows consumers that intend to avoid polymorphic
    /// code that monomorphizes. The mutable reference has all accessors of a mutable reference
    /// except it doesn't offer access with the underlying reader's type itself.
    pub fn as_mut(&mut self) -> ReaderMut<'_> {
        // Copy out all the vtable portions, we need a mutable reference to `self` for the
        // conversion into a dynamically typed `&mut dyn Read`.
        let Reader {
            inner: _,
            read: _,
            seek,
            buf,
        } = *self;

        ReaderMut {
            inner: self.as_read_mut(),
            seek,
            buf,
        }
    }

    /// Set the V-Table for [`BufRead`].
    ///
    /// After this call, the methods [`Self::as_buf`] and [`Self::as_buf_mut`] will return values.
    pub fn set_buf(&mut self)
    where
        R: BufRead,
    {
        self.buf = Some(lifetime_erase_trait_vtable!((&mut self.inner): '_ as BufRead));
    }

    /// Set the V-Table for [`Seek`].
    ///
    /// After this call, the methods [`Self::as_seek`] and [`Self::as_seek_mut`] will return values.
    pub fn set_seek(&mut self)
    where
        R: Seek,
    {
        self.seek = Some(lifetime_erase_trait_vtable!((&mut self.inner): '_ as Seek));
    }
}

impl<R> Reader<R> {
    /// Get the inner value as a dynamic `Read` reference.
    pub fn as_read(&self) -> &(dyn Read + '_) {
        let ptr = &self.inner as *const R;
        let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.read);
        unsafe { &*local }
    }

    /// Get the inner value as a mutable dynamic `Read` reference.
    pub fn as_read_mut(&mut self) -> &mut (dyn Read + '_) {
        let ptr = &mut self.inner as *mut R;
        let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.read);
        unsafe { &mut *local }
    }

    /// Get the inner value as a dynamic `BufRead` reference.
    ///
    /// This returns `None` unless a previous call to [`Self::set_buf`] as executed, by any other caller.
    /// The value can be moved after such call arbitrarily.
    pub fn as_buf(&self) -> Option<&(dyn BufRead + '_)> {
        let ptr = &self.inner as *const R;
        let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.buf?);
        Some(unsafe { &*local })
    }

    /// Get the inner value as a mutable dynamic `BufRead` reference.
    ///
    /// This returns `None` unless a previous call to [`Self::set_buf`] as executed, by any other caller.
    /// The value can be moved after such call arbitrarily.
    pub fn as_buf_mut(&mut self) -> Option<&mut (dyn BufRead + '_)> {
        let ptr = &mut self.inner as *mut R;
        let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.buf?);
        Some(unsafe { &mut *local })
    }

    /// Get the inner value as a dynamic `Seek` reference.
    ///
    /// This returns `None` unless a previous call to [`Self::set_seek`] as executed, by any other caller.
    /// The value can be moved after such call arbitrarily.
    pub fn as_seek(&self) -> Option<&(dyn Seek + '_)> {
        let ptr = &self.inner as *const R;
        let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.seek?);
        Some(unsafe { &*local })
    }

    /// Get the inner value as a mutable dynamic `Seek` reference.
    ///
    /// This returns `None` unless a previous call to [`Self::set_seek`] as executed, by any other caller.
    /// The value can be moved after such call arbitrarily.
    pub fn as_seek_mut(&mut self) -> Option<&mut (dyn Seek + '_)> {
        let ptr = &mut self.inner as *mut R;
        let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.seek?);
        Some(unsafe { &mut *local })
    }
}

impl ReaderMut<'_> {
    pub fn as_read_mut(&mut self) -> &mut (dyn Read + '_) {
        &mut *self.inner
    }

    pub fn as_buf_mut(&mut self) -> Option<&mut (dyn BufRead + '_)> {
        let ptr = self.inner as *mut dyn Read;
        let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.buf?);
        Some(unsafe { &mut *local })
    }

    pub fn as_seek_mut(&mut self) -> Option<&mut (dyn Seek + '_)> {
        let ptr = self.inner as *mut dyn Read;
        let local = WithMetadataOf::with_metadata_of_on_stable(ptr, self.seek?);
        Some(unsafe { &mut *local })
    }
}

impl<'lt, R> From<&'lt mut Reader<R>> for ReaderMut<'lt> {
    fn from(value: &'lt mut Reader<R>) -> Self {
        value.as_mut()
    }
}