Skip to main content

device_driver/
buffer.rs

1use crate::{Address, Block, ReadCapability, WriteCapability};
2use core::marker::PhantomData;
3
4/// Common properties shared by [`BufferInterface`] & [`AsyncBufferInterface`]
5pub trait BufferInterfaceBase {
6    /// The error type
7    type Error;
8    /// The address type used by this interface
9    type AddressType: Address;
10}
11
12impl<T: BufferInterfaceBase> BufferInterfaceBase for &mut T {
13    type Error = T::Error;
14    type AddressType = T::AddressType;
15}
16
17#[diagnostic::on_unimplemented(
18    label = "cannot use blocking buffer operations when the device interface doesn't know how to read and write buffers",
19    note = "to enable buffer operations, implement the trait on this type"
20)]
21/// A trait to represent the interface to the device.
22///
23/// This is called to read from and write to buffers.
24pub trait BufferInterface: BufferInterfaceBase {
25    /// Write to the buffer with the given address.
26    ///
27    /// This interface must adhere to [`embedded_io::Write::write`].
28    fn write(&mut self, address: Self::AddressType, buf: &[u8]) -> Result<usize, Self::Error>;
29    /// Flush this output stream with the given address.
30    ///
31    /// This interface must adhere to [`embedded_io::Write::flush`].
32    fn flush(&mut self, address: Self::AddressType) -> Result<(), Self::Error>;
33    /// Read from the buffer with the given address.
34    ///
35    /// This interface must adhere to [`embedded_io::Read::read`].
36    fn read(&mut self, address: Self::AddressType, buf: &mut [u8]) -> Result<usize, Self::Error>;
37}
38
39#[diagnostic::do_not_recommend]
40impl<T: BufferInterface> BufferInterface for &mut T {
41    fn write(&mut self, address: Self::AddressType, buf: &[u8]) -> Result<usize, Self::Error> {
42        (*self).write(address, buf)
43    }
44
45    fn flush(&mut self, address: Self::AddressType) -> Result<(), Self::Error> {
46        (*self).flush(address)
47    }
48
49    fn read(&mut self, address: Self::AddressType, buf: &mut [u8]) -> Result<usize, Self::Error> {
50        (*self).read(address, buf)
51    }
52}
53
54#[diagnostic::on_unimplemented(
55    label = "cannot use async buffer operations when the device interface doesn't know how to read and write buffers",
56    note = "to enable buffer operations, implement the trait on this type"
57)]
58/// A trait to represent the interface to the device.
59///
60/// This is called to read from and write to buffers.
61pub trait AsyncBufferInterface: BufferInterfaceBase {
62    /// Write to the buffer with the given address.
63    ///
64    /// This interface must adhere to [`embedded_io_async::Write::write`].
65    async fn write(&mut self, address: Self::AddressType, buf: &[u8])
66    -> Result<usize, Self::Error>;
67    /// Flush this output stream with the given address.
68    ///
69    /// This interface must adhere to [`embedded_io_async::Write::flush`].
70    async fn flush(&mut self, address: Self::AddressType) -> Result<(), Self::Error>;
71    /// Read from the buffer with the given address.
72    ///
73    /// This interface must adhere to [`embedded_io_async::Read::read`].
74    async fn read(
75        &mut self,
76        address: Self::AddressType,
77        buf: &mut [u8],
78    ) -> Result<usize, Self::Error>;
79}
80
81#[diagnostic::do_not_recommend]
82impl<T: AsyncBufferInterface> AsyncBufferInterface for &mut T {
83    fn write(
84        &mut self,
85        address: Self::AddressType,
86        buf: &[u8],
87    ) -> impl Future<Output = Result<usize, Self::Error>> {
88        (*self).write(address, buf)
89    }
90
91    fn flush(
92        &mut self,
93        address: Self::AddressType,
94    ) -> impl Future<Output = Result<(), Self::Error>> {
95        (*self).flush(address)
96    }
97
98    fn read(
99        &mut self,
100        address: Self::AddressType,
101        buf: &mut [u8],
102    ) -> impl Future<Output = Result<usize, Self::Error>> {
103        (*self).read(address, buf)
104    }
105}
106
107/// Intermediate type for doing buffer operations
108///
109/// If the interface error implements [`embedded_io::Error`],
110/// then this operation type also implements the [`embedded_io`] traits
111pub struct BufferOperation<'b, B, AddressType, Access>
112where
113    B: Block,
114    B::Interface: BufferInterfaceBase<AddressType = AddressType>,
115    AddressType: Address,
116{
117    block: &'b mut B,
118    address: AddressType,
119    _phantom: PhantomData<Access>,
120}
121
122impl<'b, B, AddressType, Access> BufferOperation<'b, B, AddressType, Access>
123where
124    B: Block,
125    B::Interface: BufferInterfaceBase<AddressType = AddressType>,
126    AddressType: Address,
127{
128    #[doc(hidden)]
129    pub fn new(
130        interface: &'b mut B,
131        address: <B::Interface as BufferInterfaceBase>::AddressType,
132    ) -> Self {
133        Self {
134            block: interface,
135            address,
136            _phantom: PhantomData,
137        }
138    }
139    /// Write a buffer into this writer, returning how many bytes were written.
140    ///
141    /// Mirror function of [`embedded_io::Write::write`].
142    pub fn write(
143        &mut self,
144        buf: &[u8],
145    ) -> Result<usize, <B::Interface as BufferInterfaceBase>::Error>
146    where
147        B::Interface: BufferInterface,
148        Access: WriteCapability,
149    {
150        self.block.interface().write(self.address, buf)
151    }
152
153    /// Write a buffer into this writer, returning how many bytes were written.
154    ///
155    /// Mirror function of [`embedded_io_async::Write::write`].
156    pub fn write_async(
157        &mut self,
158        buf: &[u8],
159    ) -> impl Future<Output = Result<usize, <B::Interface as BufferInterfaceBase>::Error>>
160    where
161        B::Interface: AsyncBufferInterface,
162        Access: WriteCapability,
163    {
164        self.block.interface().write(self.address, buf)
165    }
166
167    /// Write an entire buffer into this writer.
168    ///
169    /// This function calls `write()` in a loop until exactly `buf.len()` bytes have been written, blocking if needed.
170    ///
171    /// Mirror function of [`embedded_io::Write::write_all`].
172    pub fn write_all(
173        &mut self,
174        mut buf: &[u8],
175    ) -> Result<(), <B::Interface as BufferInterfaceBase>::Error>
176    where
177        B::Interface: BufferInterface,
178        Access: WriteCapability,
179    {
180        while !buf.is_empty() {
181            match self.write(buf) {
182                Ok(0) => panic!("write() returned Ok(0)"),
183                Ok(n) => buf = &buf[n..],
184                Err(e) => return Err(e),
185            }
186        }
187        Ok(())
188    }
189
190    /// Write an entire buffer into this writer.
191    ///
192    /// This function calls `write()` in a loop until exactly `buf.len()` bytes have been written, blocking if needed.
193    ///
194    /// Mirror function of [`embedded_io_async::Write::write_all`].
195    pub async fn write_all_async(
196        &mut self,
197        mut buf: &[u8],
198    ) -> Result<(), <B::Interface as BufferInterfaceBase>::Error>
199    where
200        B::Interface: AsyncBufferInterface,
201        Access: WriteCapability,
202    {
203        while !buf.is_empty() {
204            match self.write_async(buf).await {
205                Ok(0) => panic!("write() returned Ok(0)"),
206                Ok(n) => buf = &buf[n..],
207                Err(e) => return Err(e),
208            }
209        }
210        Ok(())
211    }
212
213    /// Flush this output stream, blocking until all intermediately buffered contents reach their destination.
214    ///
215    /// Mirror function of [`embedded_io::Write::flush`].
216    pub fn flush(&mut self) -> Result<(), <B::Interface as BufferInterfaceBase>::Error>
217    where
218        B::Interface: BufferInterface,
219        Access: WriteCapability,
220    {
221        self.block.interface().flush(self.address)
222    }
223
224    /// Flush this output stream, blocking until all intermediately buffered contents reach their destination.
225    ///
226    /// Mirror function of [`embedded_io_async::Write::flush`].
227    pub fn flush_async(
228        &mut self,
229    ) -> impl Future<Output = Result<(), <B::Interface as BufferInterfaceBase>::Error>>
230    where
231        B::Interface: AsyncBufferInterface,
232        Access: WriteCapability,
233    {
234        self.block.interface().flush(self.address)
235    }
236
237    /// Read some bytes from this source into the specified buffer, returning how many bytes were read.
238    ///
239    /// Mirror function of [`embedded_io::Read::read`].
240    pub fn read(
241        &mut self,
242        buf: &mut [u8],
243    ) -> Result<usize, <B::Interface as BufferInterfaceBase>::Error>
244    where
245        B::Interface: BufferInterface,
246        Access: ReadCapability,
247    {
248        self.block.interface().read(self.address, buf)
249    }
250
251    /// Read some bytes from this source into the specified buffer, returning how many bytes were read.
252    ///
253    /// Mirror function of [`embedded_io_async::Read::read`].
254    pub fn read_async(
255        &mut self,
256        buf: &mut [u8],
257    ) -> impl Future<Output = Result<usize, <B::Interface as BufferInterfaceBase>::Error>>
258    where
259        B::Interface: AsyncBufferInterface,
260        Access: ReadCapability,
261    {
262        self.block.interface().read(self.address, buf)
263    }
264}
265
266// ------- embedded-io impls -------
267
268#[cfg(feature = "embedded-io-07")]
269impl<B, AddressType, Access> embedded_io::ErrorType for BufferOperation<'_, B, AddressType, Access>
270where
271    B: Block,
272    B::Interface: BufferInterfaceBase<AddressType = AddressType>,
273    <B::Interface as BufferInterfaceBase>::Error: embedded_io::Error,
274    AddressType: Address,
275{
276    type Error = <B::Interface as BufferInterfaceBase>::Error;
277}
278
279#[cfg(feature = "embedded-io-07")]
280impl<B, AddressType, Access> embedded_io::Write for BufferOperation<'_, B, AddressType, Access>
281where
282    B: Block,
283    B::Interface: BufferInterface<AddressType = AddressType>,
284    <B::Interface as BufferInterfaceBase>::Error: embedded_io::Error,
285    Access: WriteCapability,
286    AddressType: Address,
287{
288    fn write(&mut self, buf: &[u8]) -> Result<usize, Self::Error> {
289        self.write(buf)
290    }
291
292    fn flush(&mut self) -> Result<(), Self::Error> {
293        self.flush()
294    }
295}
296
297#[cfg(feature = "embedded-io-07")]
298impl<B, AddressType, Access> embedded_io::Read for BufferOperation<'_, B, AddressType, Access>
299where
300    B: Block,
301    B::Interface: BufferInterface<AddressType = AddressType>,
302    <B::Interface as BufferInterfaceBase>::Error: embedded_io::Error,
303    Access: ReadCapability,
304    AddressType: Address,
305{
306    fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
307        self.read(buf)
308    }
309}
310
311#[cfg(feature = "embedded-io-07")]
312impl<B, AddressType, Access> embedded_io_async::Write
313    for BufferOperation<'_, B, AddressType, Access>
314where
315    B: Block,
316    B::Interface: AsyncBufferInterface<AddressType = AddressType>,
317    <B::Interface as BufferInterfaceBase>::Error: embedded_io::Error,
318    Access: WriteCapability,
319    AddressType: Address,
320{
321    fn write(&mut self, buf: &[u8]) -> impl Future<Output = Result<usize, Self::Error>> {
322        self.write_async(buf)
323    }
324
325    fn flush(&mut self) -> impl Future<Output = Result<(), Self::Error>> {
326        self.flush_async()
327    }
328}
329
330#[cfg(feature = "embedded-io-07")]
331impl<B, AddressType, Access> embedded_io_async::Read for BufferOperation<'_, B, AddressType, Access>
332where
333    B: Block,
334    B::Interface: AsyncBufferInterface<AddressType = AddressType>,
335    <B::Interface as BufferInterfaceBase>::Error: embedded_io::Error,
336    Access: ReadCapability,
337    AddressType: Address,
338{
339    fn read(&mut self, buf: &mut [u8]) -> impl Future<Output = Result<usize, Self::Error>> {
340        self.read_async(buf)
341    }
342}