#![cfg(feature = "std")]
use crate::{TryNext, TryNextWithContext};
use std::io::{self, BufRead, BufReader, Read};
impl<R, C> TryNextWithContext<C> for BufReader<R>
where
R: Read,
{
type Item = u8;
type Error = io::Error;
fn try_next_with_context(&mut self, _context: &mut C) -> Result<Option<Self::Item>, Self::Error> {
let buf = self.fill_buf()?;
if buf.is_empty() {
return Ok(None);
}
let b = buf[0];
self.consume(1);
Ok(Some(b))
}
}
impl<R> TryNext for BufReader<R>
where
R: Read,
{
type Item = u8;
type Error = io::Error;
fn try_next(&mut self) -> Result<Option<Self::Item>, Self::Error> {
let buf = self.fill_buf()?;
if buf.is_empty() {
return Ok(None);
}
let b = buf[0];
self.consume(1);
Ok(Some(b))
}
}
#[cfg(test)]
mod tests {
use super::*;
use std::io::{self, Read};
#[test]
fn try_next_reads_each_byte_then_none() {
let data = b"abc";
let mut rdr = BufReader::new(&data[..]);
assert_eq!(rdr.try_next().unwrap(), Some(b'a'));
assert_eq!(rdr.try_next().unwrap(), Some(b'b'));
assert_eq!(rdr.try_next().unwrap(), Some(b'c'));
assert_eq!(rdr.try_next().unwrap(), None); assert_eq!(rdr.try_next().unwrap(), None); }
#[test]
fn try_next_with_context_reads_bytes_and_reaches_eof() {
let data = b"xy";
let mut rdr = BufReader::new(&data[..]);
let mut ctx = ();
assert_eq!(rdr.try_next_with_context(&mut ctx).unwrap(), Some(b'x'));
assert_eq!(rdr.try_next_with_context(&mut ctx).unwrap(), Some(b'y'));
assert_eq!(rdr.try_next_with_context(&mut ctx).unwrap(), None);
}
#[test]
fn try_next_on_empty_input_is_none() {
let data: &[u8] = b"";
let mut rdr = BufReader::new(&data[..]);
assert_eq!(rdr.try_next().unwrap(), None);
}
#[test]
fn try_next_with_context_on_empty_input_is_none() {
let data: &[u8] = b"";
let mut rdr = BufReader::new(&data[..]);
let mut ctx = ();
assert_eq!(rdr.try_next_with_context(&mut ctx).unwrap(), None);
}
struct Boom;
impl Read for Boom {
fn read(&mut self, _buf: &mut [u8]) -> io::Result<usize> {
Err(io::Error::new(io::ErrorKind::Other, "boom"))
}
}
#[test]
fn try_next_propagates_errors() {
let mut rdr = BufReader::new(Boom);
let err = rdr.try_next().unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::Other);
assert_eq!(err.to_string(), "boom");
}
#[test]
fn try_next_with_context_propagates_errors() {
let mut rdr = BufReader::new(Boom);
let mut ctx = ();
let err = rdr.try_next_with_context(&mut ctx).unwrap_err();
assert_eq!(err.kind(), io::ErrorKind::Other);
assert_eq!(err.to_string(), "boom");
}
}