1use crate::{Address, Block, ReadCapability, WriteCapability};
2use core::marker::PhantomData;
3
4pub trait BufferInterfaceBase {
6 type Error;
8 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)]
21pub trait BufferInterface: BufferInterfaceBase {
25 fn write(&mut self, address: Self::AddressType, buf: &[u8]) -> Result<usize, Self::Error>;
29 fn flush(&mut self, address: Self::AddressType) -> Result<(), Self::Error>;
33 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)]
58pub trait AsyncBufferInterface: BufferInterfaceBase {
62 async fn write(&mut self, address: Self::AddressType, buf: &[u8])
66 -> Result<usize, Self::Error>;
67 async fn flush(&mut self, address: Self::AddressType) -> Result<(), Self::Error>;
71 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
107pub 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 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 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 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 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 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 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 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 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#[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}