Skip to content

Commit 74c4e55

Browse files
author
Dane Slattery
committed
Add BufReader impl
1 parent bbd5803 commit 74c4e55

File tree

1 file changed

+143
-0
lines changed

1 file changed

+143
-0
lines changed

embedded-io/src/lib.rs

Lines changed: 143 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -339,6 +339,107 @@ pub trait Read: ErrorType {
339339
}
340340
}
341341

342+
/// The [BufReader] adds buffering to any reader, analogous to [`std::io::BufReader`]
343+
///
344+
/// This [BufReader] allocates it's own internal buffer of size [N].
345+
///
346+
/// # Examples
347+
///
348+
/// ```
349+
/// use embedded_io::BufReader;
350+
///
351+
/// fn main()-> Result<(),>
352+
/// {
353+
/// let reader = [0,1,2,3];
354+
/// let mut buf_reader: BufReader<4,&[u8]> = BufReader::new(&reader);
355+
///
356+
/// let current_buff = buf_reader.fill_buff()?;
357+
///
358+
/// buf_reader.consume(4);
359+
///
360+
/// }
361+
///
362+
/// ```
363+
pub struct BufReader<const N: usize, R: ?Sized> {
364+
buff: [u8; N],
365+
pos: usize,
366+
inner: R,
367+
}
368+
369+
impl<const N: usize, R: ?Sized> BufReader<N, R> {
370+
/// Gets a reference to the underlying reader.
371+
pub fn get_ref(&self) -> &R {
372+
&self.inner
373+
}
374+
375+
pub fn get_mut(&mut self) -> &mut R {
376+
&mut self.inner
377+
}
378+
379+
pub fn buffer(&self) -> &[u8] {
380+
&self.buff
381+
}
382+
383+
pub fn capacity(&self) -> usize {
384+
N
385+
}
386+
387+
pub fn into_inner(self) -> R
388+
where
389+
R: Sized,
390+
{
391+
self.inner
392+
}
393+
394+
pub fn discard_buffer(&mut self) {
395+
self.pos = 0;
396+
}
397+
}
398+
399+
impl<const N: usize, R: Read> BufReader<N, R> {
400+
/// Creates a new [BufReader<N,R>] with a buffer capacity of `N`.
401+
pub fn new(reader: R) -> Self {
402+
Self {
403+
buff: [0u8; N],
404+
pos: 0,
405+
inner: reader,
406+
}
407+
}
408+
}
409+
410+
impl<const N: usize, R: Read> ErrorType for BufReader<N, R> {
411+
type Error = R::Error;
412+
}
413+
414+
impl<const N: usize, R: Read> BufRead for BufReader<N, R> {
415+
fn consume(&mut self, amt: usize) {
416+
// remove amt bytes from the front of the buffer
417+
// imagine the buffer is [0,1,2,3,4]
418+
// consume(2)
419+
// the buffer is now [2,3,4]
420+
self.buff.copy_within(amt..self.pos, 0);
421+
self.pos -= amt;
422+
}
423+
424+
fn fill_buf(&mut self) -> Result<&[u8], Self::Error> {
425+
// fill the inner buffer
426+
let read_count = self.inner.read(&mut self.buff[self.pos..])?;
427+
self.pos += read_count;
428+
429+
Ok(&self.buff[..self.pos])
430+
}
431+
}
432+
433+
impl<const N: usize, R: Read> Read for BufReader<N, R> {
434+
fn read(&mut self, buf: &mut [u8]) -> Result<usize, Self::Error> {
435+
let mut rem = self.fill_buf()?;
436+
let nread = rem.read(buf).unwrap(); // infallible
437+
438+
self.consume(nread);
439+
Ok(nread)
440+
}
441+
}
442+
342443
/// Blocking buffered reader.
343444
///
344445
/// This trait is the `embedded-io` equivalent of [`std::io::BufRead`].
@@ -551,3 +652,45 @@ impl<T: ?Sized + WriteReady> WriteReady for &mut T {
551652
T::write_ready(self)
552653
}
553654
}
655+
656+
#[cfg(test)]
657+
mod tests {
658+
use super::*;
659+
660+
#[test]
661+
fn bufread_consume_removes_bytes() {
662+
let reader = [0, 1, 2, 3];
663+
664+
let mut buf_read: BufReader<4, &[u8]> = BufReader::new(&reader);
665+
666+
// read bytes
667+
let current_buff = buf_read.fill_buf().unwrap();
668+
669+
assert_eq!(current_buff, [0, 1, 2, 3]);
670+
671+
// consume bytes
672+
buf_read.consume(2);
673+
674+
assert_eq!(buf_read.fill_buf().unwrap(), [2, 3]);
675+
}
676+
677+
#[test]
678+
#[should_panic]
679+
fn bufread_panics_if_consume_more_than_n_bytes() {
680+
let reader = [0, 1, 2, 3];
681+
682+
let mut buf_read: BufReader<4, &[u8]> = BufReader::new(&reader);
683+
684+
buf_read.consume(5);
685+
}
686+
687+
#[test]
688+
#[should_panic]
689+
fn bufread_panics_if_consume_more_bytes_than_filled() {
690+
let reader = [0, 1, 2, 3];
691+
692+
let mut buf_read: BufReader<4, &[u8]> = BufReader::new(&reader);
693+
694+
buf_read.consume(4);
695+
}
696+
}

0 commit comments

Comments
 (0)