Skip to main content

circular_buffer/
embedded_io.rs

1// Copyright © 2023-2026 Andrea Corbellini and contributors
2// SPDX-License-Identifier: BSD-3-Clause
3
4#![cfg(any(feature = "embedded-io", feature = "embedded-io-async"))]
5
6use crate::CircularBuffer;
7use crate::FixedCircularBuffer;
8use core::convert::Infallible;
9use core::ops::DerefMut;
10
11#[cfg(feature = "alloc")]
12use crate::HeapCircularBuffer;
13
14#[cfg(feature = "embedded-io")]
15use embedded_io::ErrorType;
16
17#[cfg(all(feature = "embedded-io-async", not(feature = "embedded-io")))]
18use embedded_io_async::ErrorType;
19
20impl ErrorType for CircularBuffer<u8> {
21    type Error = Infallible;
22}
23
24#[cfg(feature = "embedded-io")]
25impl embedded_io::Write for CircularBuffer<u8> {
26    #[inline]
27    fn write(&mut self, src: &[u8]) -> Result<usize, Self::Error> {
28        self.extend_from_slice(src);
29        Ok(src.len())
30    }
31
32    #[inline]
33    fn flush(&mut self) -> Result<(), Self::Error> {
34        Ok(())
35    }
36}
37
38#[cfg(feature = "embedded-io")]
39impl embedded_io::Read for CircularBuffer<u8> {
40    fn read(&mut self, dst: &mut [u8]) -> Result<usize, Self::Error> {
41        let (mut front, mut back) = self.as_slices();
42        let mut count = front.read(dst)?;
43        count += back.read(&mut dst[count..])?;
44        let truncate_to = self.len() - count;
45        self.truncate_front(truncate_to);
46        Ok(count)
47    }
48}
49
50#[cfg(feature = "embedded-io")]
51impl embedded_io::BufRead for CircularBuffer<u8> {
52    fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
53        let (front, back) = self.as_slices();
54        if !front.is_empty() {
55            Ok(front)
56        } else {
57            Ok(back)
58        }
59    }
60
61    fn consume(&mut self, amt: usize) {
62        let amt = core::cmp::min(amt, self.len());
63        self.drain(..amt);
64    }
65}
66
67#[cfg(feature = "embedded-io-async")]
68impl embedded_io_async::Write for CircularBuffer<u8> {
69    #[inline]
70    async fn flush(&mut self) -> Result<(), Self::Error> {
71        Ok(())
72    }
73
74    #[inline]
75    async fn write(&mut self, src: &[u8]) -> Result<usize, Self::Error> {
76        self.extend_from_slice(src);
77        Ok(src.len())
78    }
79}
80
81#[cfg(feature = "embedded-io-async")]
82impl embedded_io_async::Read for CircularBuffer<u8> {
83    async fn read(&mut self, dst: &mut [u8]) -> Result<usize, Self::Error> {
84        let (mut front, mut back) = self.as_slices();
85        let mut count = front.read(dst).await?;
86        count += back.read(&mut dst[count..]).await?;
87        let truncate_to = self.len() - count;
88        self.truncate_front(truncate_to);
89        Ok(count)
90    }
91}
92
93#[cfg(feature = "embedded-io-async")]
94impl embedded_io_async::BufRead for CircularBuffer<u8> {
95    async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
96        let (front, back) = self.as_slices();
97        if !front.is_empty() {
98            Ok(front)
99        } else {
100            Ok(back)
101        }
102    }
103
104    fn consume(&mut self, amt: usize) {
105        let amt = core::cmp::min(amt, self.len());
106        self.drain(..amt);
107    }
108}
109
110impl<const N: usize> ErrorType for FixedCircularBuffer<u8, N> {
111    type Error = Infallible;
112}
113
114#[cfg(feature = "embedded-io")]
115impl<const N: usize> embedded_io::Write for FixedCircularBuffer<u8, N> {
116    #[inline]
117    fn write(&mut self, src: &[u8]) -> Result<usize, Self::Error> {
118        self.deref_mut().write(src)
119    }
120
121    #[inline]
122    fn flush(&mut self) -> Result<(), Self::Error> {
123        self.deref_mut().flush()
124    }
125}
126
127#[cfg(feature = "embedded-io")]
128impl<const N: usize> embedded_io::Read for FixedCircularBuffer<u8, N> {
129    #[inline]
130    fn read(&mut self, dst: &mut [u8]) -> Result<usize, Self::Error> {
131        self.deref_mut().read(dst)
132    }
133}
134
135#[cfg(feature = "embedded-io")]
136impl<const N: usize> embedded_io::BufRead for FixedCircularBuffer<u8, N> {
137    #[inline]
138    fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
139        self.deref_mut().fill_buf()
140    }
141
142    #[inline]
143    fn consume(&mut self, amt: usize) {
144        self.deref_mut().consume(amt)
145    }
146}
147
148#[cfg(feature = "embedded-io-async")]
149impl<const N: usize> embedded_io_async::Write for FixedCircularBuffer<u8, N> {
150    #[inline]
151    async fn flush(&mut self) -> Result<(), Self::Error> {
152        self.deref_mut().flush().await
153    }
154
155    #[inline]
156    async fn write(&mut self, src: &[u8]) -> Result<usize, Self::Error> {
157        self.deref_mut().write(src).await
158    }
159}
160
161#[cfg(feature = "embedded-io-async")]
162impl<const N: usize> embedded_io_async::Read for FixedCircularBuffer<u8, N> {
163    #[inline]
164    async fn read(&mut self, dst: &mut [u8]) -> Result<usize, Self::Error> {
165        self.deref_mut().read(dst).await
166    }
167}
168
169#[cfg(feature = "embedded-io-async")]
170impl<const N: usize> embedded_io_async::BufRead for FixedCircularBuffer<u8, N> {
171    #[inline]
172    async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
173        self.deref_mut().fill_buf().await
174    }
175
176    #[inline]
177    fn consume(&mut self, amt: usize) {
178        self.deref_mut().consume(amt)
179    }
180}
181
182#[cfg(feature = "alloc")]
183impl ErrorType for HeapCircularBuffer<u8> {
184    type Error = Infallible;
185}
186
187#[cfg(feature = "alloc")]
188#[cfg(feature = "embedded-io")]
189impl embedded_io::Write for HeapCircularBuffer<u8> {
190    #[inline]
191    fn write(&mut self, src: &[u8]) -> Result<usize, Self::Error> {
192        self.deref_mut().write(src)
193    }
194
195    #[inline]
196    fn flush(&mut self) -> Result<(), Self::Error> {
197        self.deref_mut().flush()
198    }
199}
200
201#[cfg(feature = "alloc")]
202#[cfg(feature = "embedded-io")]
203impl embedded_io::Read for HeapCircularBuffer<u8> {
204    #[inline]
205    fn read(&mut self, dst: &mut [u8]) -> Result<usize, Self::Error> {
206        self.deref_mut().read(dst)
207    }
208}
209
210#[cfg(feature = "alloc")]
211#[cfg(feature = "embedded-io")]
212impl embedded_io::BufRead for HeapCircularBuffer<u8> {
213    #[inline]
214    fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
215        self.deref_mut().fill_buf()
216    }
217
218    #[inline]
219    fn consume(&mut self, amt: usize) {
220        self.deref_mut().consume(amt)
221    }
222}
223
224#[cfg(feature = "alloc")]
225#[cfg(feature = "embedded-io-async")]
226impl embedded_io_async::Write for HeapCircularBuffer<u8> {
227    #[inline]
228    async fn flush(&mut self) -> Result<(), Self::Error> {
229        self.deref_mut().flush().await
230    }
231
232    #[inline]
233    async fn write(&mut self, src: &[u8]) -> Result<usize, Self::Error> {
234        self.deref_mut().write(src).await
235    }
236}
237
238#[cfg(feature = "alloc")]
239#[cfg(feature = "embedded-io-async")]
240impl embedded_io_async::Read for HeapCircularBuffer<u8> {
241    #[inline]
242    async fn read(&mut self, dst: &mut [u8]) -> Result<usize, Self::Error> {
243        self.deref_mut().read(dst).await
244    }
245}
246
247#[cfg(feature = "alloc")]
248#[cfg(feature = "embedded-io-async")]
249impl embedded_io_async::BufRead for HeapCircularBuffer<u8> {
250    #[inline]
251    async fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
252        self.deref_mut().fill_buf().await
253    }
254
255    #[inline]
256    fn consume(&mut self, amt: usize) {
257        self.deref_mut().consume(amt)
258    }
259}