AOJXTWBZA2DQBFTJZX2YTGAKIB62SKTEVJ7RRIBJNDSMC75DDQVQC //! adapted from the answer to this question: https://users.rust-lang.org/t/bufread-read-until-with-two-byte-delimiter/47239/6//! playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018use bstr::ByteSlice;use std::io;use std::io::BufRead;/// Find the delimiter in the excess and the buffer, and return:/// Whether it was located/// How much was read into the bufferfn step<const N: usize>(excess: &[u8], delimeter: &[u8; N], buf: &mut Vec<u8>) -> (bool, usize) {// find the whole delimiter in the excessif let Some(i) = excess.find(&delimeter) {buf.extend_from_slice(&excess[..i + N]);return (true, i + N);}// find the delimiter if it is partly in the excess and partly in the bufferfor n in 1..N {// the seam between buf and excess contains the delimterif buf.ends_with(&delimeter[..n]) && excess.starts_with(&delimeter[n..N]) {let used = N - n;// then extend buf to include what needed to be read past the splitbuf.extend_from_slice(&excess[..used]);return (true, used);}}buf.extend_from_slice(excess);(false, excess.len())}pub fn read_until<R, const N: usize>(reader: &mut R,delimeter: &[u8; N],buf: &mut Vec<u8>,) -> io::Result<usize>whereR: BufRead + ?Sized,{let mut read = 0;loop {// read aheadlet (done, used) = step(reader.fill_buf()?, delimeter, buf);reader.consume(used);// count the number of bytes consumedread += used;// done means we found it, used == 0 means eofif done || used == 0 {return Ok(read);}}}#[cfg(test)]mod test {use crate::read_until::read_until;use std::io::BufReader;#[test]fn read1() {let mut buf0: &[u8] = b"ebfdefghijkl";let mut buf1 = Vec::new();let exp = b"ebf";let mut bufread = BufReader::new(&mut buf0);read_until(&mut bufread, b"f", &mut buf1).unwrap();assert_eq!(buf1, exp);}#[test]fn read2() {let mut buf0: &[u8] = b"ebfdefghijkl";let mut buf1 = Vec::new();let exp = b"ebfdef";let mut bufread = BufReader::new(&mut buf0);read_until(&mut bufread, b"ef", &mut buf1).unwrap();assert_eq!(buf1, exp);}#[test]fn read3() {let mut buf0: &[u8] = b"ebfdefghijkl";let mut buf1 = Vec::new();let exp = b"ebfdef";let mut bufread = BufReader::new(&mut buf0);read_until(&mut bufread, b"def", &mut buf1).unwrap();assert_eq!(buf1, exp);}#[test]fn read4() {let mut buf0: &[u8] = b"ebfdefghijkl";let mut buf1 = Vec::new();let exp = b"ebfdef";let mut bufread = BufReader::new(&mut buf0);read_until(&mut bufread, b"fdef", &mut buf1).unwrap();assert_eq!(buf1, exp);}#[test]fn read5() {let mut buf0: &[u8] = b"ebfdefghijkl";let mut buf1 = Vec::new();let exp = b"ebfdef";let mut bufread = BufReader::new(&mut buf0);read_until(&mut bufread, b"bfdef", &mut buf1).unwrap();assert_eq!(buf1, exp);}#[test]fn read6() {let mut buf0: &[u8] = b"ebfdefghijkl";let mut buf1 = Vec::new();let exp = b"ebfdef";let mut bufread = BufReader::new(&mut buf0);read_until(&mut bufread, b"ebfdef", &mut buf1).unwrap();assert_eq!(buf1, exp);}}
use std::io::{Read, Result};
use std::io::{BufRead, Read, Result};pub trait ReadExt {fn read_byte(&mut self) -> Result<u8>;fn read_n<const N: usize>(&mut self) -> Result<[u8; N]>;fn read_string(&mut self) -> Result<String>;}pub trait BufReadExt {fn read_until<const N: usize>(&mut self,delimeter: &[u8; N],buf: &mut Vec<u8>,) -> Result<usize>;}
pub(crate) fn read_byte(stream: &mut impl Read) -> Result<u8> {let [c] = read_n::<1>(stream)?;Ok(c)
impl<R: Read> ReadExt for R {fn read_byte(&mut self) -> Result<u8> {let [c] = self.read_n::<1>()?;Ok(c)}fn read_n<const N: usize>(&mut self) -> Result<[u8; N]> {let mut buf = [0; N];self.read_exact(&mut buf)?;Ok(buf)}fn read_string(&mut self) -> Result<String> {let mut body = String::new();self.read_to_string(&mut body)?;Ok(body)}
mod read_until {//! adapted from the answer to this question: https://users.rust-lang.org/t/bufread-read-until-with-two-byte-delimiter/47239/6//! playground link: https://play.rust-lang.org/?version=stable&mode=debug&edition=2018use bstr::ByteSlice;use std::io::BufRead;use std::io::Result;
pub(crate) fn read_n<const N: usize>(stream: &mut impl Read) -> Result<[u8; N]> {let mut buf = [0; N];stream.read_exact(&mut buf)?;Ok(buf)
use super::BufReadExt;/// Find the delimiter in the excess and the buffer, and return:/// Whether it was located/// How much was read into the bufferfn step<const N: usize>(excess: &[u8],delimeter: &[u8; N],buf: &mut Vec<u8>,) -> (bool, usize) {// find the whole delimiter in the excessif let Some(i) = excess.find(&delimeter) {buf.extend_from_slice(&excess[..i + N]);return (true, i + N);}// find the delimiter if it is partly in the excess and partly in the bufferfor n in 1..N {// the seam between buf and excess contains the delimterif buf.ends_with(&delimeter[..n]) && excess.starts_with(&delimeter[n..N]) {let used = N - n;// then extend buf to include what needed to be read past the splitbuf.extend_from_slice(&excess[..used]);return (true, used);}}buf.extend_from_slice(excess);(false, excess.len())}impl<R: BufRead> BufReadExt for R {fn read_until<const N: usize>(&mut self,delimiter: &[u8; N],buf: &mut Vec<u8>,) -> Result<usize> {let mut read = 0;loop {// read aheadlet (done, used) = step(self.fill_buf()?, delimiter, buf);self.consume(used);// count the number of bytes consumedread += used;// done means we found it, used == 0 means eofif done || used == 0 {return Ok(read);}}}}#[cfg(test)]mod test {use super::BufReadExt;use std::io::BufReader;#[test]fn read1() {let mut buf0: &[u8] = b"ebfdefghijkl";let mut buf1 = Vec::new();let exp = b"ebf";let mut bufread = BufReader::new(&mut buf0);bufread.read_until(b"f", &mut buf1).unwrap();assert_eq!(buf1, exp);}#[test]fn read2() {let mut buf0: &[u8] = b"ebfdefghijkl";let mut buf1 = Vec::new();let exp = b"ebfdef";let mut bufread = BufReader::new(&mut buf0);bufread.read_until(b"ef", &mut buf1).unwrap();assert_eq!(buf1, exp);}#[test]fn read3() {let mut buf0: &[u8] = b"ebfdefghijkl";let mut buf1 = Vec::new();let exp = b"ebfdef";let mut bufread = BufReader::new(&mut buf0);bufread.read_until(b"def", &mut buf1).unwrap();assert_eq!(buf1, exp);}#[test]fn read4() {let mut buf0: &[u8] = b"ebfdefghijkl";let mut buf1 = Vec::new();let exp = b"ebfdef";let mut bufread = BufReader::new(&mut buf0);bufread.read_until(b"fdef", &mut buf1).unwrap();assert_eq!(buf1, exp);}#[test]fn read5() {let mut buf0: &[u8] = b"ebfdefghijkl";let mut buf1 = Vec::new();let exp = b"ebfdef";let mut bufread = BufReader::new(&mut buf0);bufread.read_until(b"bfdef", &mut buf1).unwrap();assert_eq!(buf1, exp);}#[test]fn read6() {let mut buf0: &[u8] = b"ebfdefghijkl";let mut buf1 = Vec::new();let exp = b"ebfdef";let mut bufread = BufReader::new(&mut buf0);bufread.read_until(b"ebfdef", &mut buf1).unwrap();assert_eq!(buf1, exp);}}