From ed844a997cf7211a61a317a7103b6c131c74aaf9 Mon Sep 17 00:00:00 2001 From: Bert Peters Date: Thu, 2 Dec 2021 08:34:14 +0100 Subject: [PATCH] Create reusable line reader --- 2021/src/common.rs | 43 ++++++++++++++++++++++++++++++------------- 2021/src/day02.rs | 14 +++++--------- 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/2021/src/common.rs b/2021/src/common.rs index 3cb3826..ad978b3 100644 --- a/2021/src/common.rs +++ b/2021/src/common.rs @@ -4,6 +4,33 @@ use std::io::Read; use std::marker::PhantomData; use std::str::FromStr; +pub struct LineIter<'a> { + reader: BufReader<&'a mut dyn Read>, + buffer: String, +} + +impl<'a> LineIter<'a> { + pub fn new(input: &'a mut dyn Read) -> Self { + Self { + reader: BufReader::new(input), + buffer: String::new(), + } + } + + /// Get the next line, or None + /// + /// This is deliberately not an [Iterator] impl as those cannot hand out references to self. + pub fn next(&mut self) -> Option<&str> { + self.buffer.clear(); + + if matches!(self.reader.read_line(&mut self.buffer), Ok(n) if n > 0) { + Some(self.buffer.trim_end_matches('\n')) + } else { + None + } + } +} + /// Line-based iterator/parser /// /// For each line of the input, attempt to parse it as the requested type. Iteration is stopped on @@ -13,33 +40,23 @@ pub struct LineParser<'a, I> where I: FromStr, { - reader: BufReader<&'a mut dyn Read>, - buffer: String, + iter: LineIter<'a>, _data: PhantomData, } impl<'a, I: FromStr> LineParser<'a, I> { pub fn new(input: &'a mut dyn Read) -> Self { Self { - reader: BufReader::new(input), - buffer: String::new(), + iter: LineIter::new(input), _data: PhantomData, } } - - fn next_line(&mut self) -> Option<&str> { - self.buffer.clear(); - - self.reader.read_line(&mut self.buffer).ok()?; - - Some(self.buffer.trim()) - } } impl<'a, I: FromStr> Iterator for LineParser<'a, I> { type Item = I; fn next(&mut self) -> Option { - self.next_line()?.parse().ok() + self.iter.next()?.parse().ok() } } diff --git a/2021/src/day02.rs b/2021/src/day02.rs index 1e29efb..d68b612 100644 --- a/2021/src/day02.rs +++ b/2021/src/day02.rs @@ -1,7 +1,7 @@ -use std::io::BufRead; -use std::io::BufReader; use std::io::Read; +use crate::common::LineIter; + enum Dir { Up, Down, @@ -9,13 +9,11 @@ enum Dir { } fn parse_input(input: &mut dyn Read) -> Vec<(Dir, i32)> { - let mut reader = BufReader::new(input); - let mut buffer = String::new(); - + let mut reader = LineIter::new(input); let mut moves = Vec::new(); - while matches!(reader.read_line(&mut buffer), Ok(n) if n > 0) { - let (dir, amount) = buffer.trim().split_once(" ").unwrap(); + while let Some(line) = reader.next() { + let (dir, amount) = line.split_once(" ").unwrap(); let dir = match dir { "up" => Dir::Up, @@ -25,8 +23,6 @@ fn parse_input(input: &mut dyn Read) -> Vec<(Dir, i32)> { }; moves.push((dir, amount.parse().unwrap())); - - buffer.clear(); } moves