Skip to content

Instantly share code, notes, and snippets.

@alexisvisco
Last active December 1, 2019 18:44
Show Gist options
  • Save alexisvisco/bc8a812c277a16694d08fcd6273813d5 to your computer and use it in GitHub Desktop.
Save alexisvisco/bc8a812c277a16694d08fcd6273813d5 to your computer and use it in GitHub Desktop.
Read a BufReader with a BUFFER_SIZE and with each read ending with a \n
fn consume_buffer(buffer_reader: &mut BufReader<&File>) -> Option<String> {
let mut full_line = String::new();
'outer: loop {
match buffer_reader.fill_buf() {
Ok(buffer) => {
let buffer_str = String::from_utf8(buffer.to_vec()).unwrap_or(String::new());
// A previous buffer has been read.
// It was without '\n' termination so it must read until it find a '\n'.
if !full_line.is_empty() {
match buffer_str.lines().next() {
Some(first_line) => {
let line_length = first_line.len();
full_line.push_str(first_line.to_owned().as_str());
// Since the length of the line is the same as current buffer length
// there is still no '\n' end so keep continue reading.
// Cover the case when the read line is empty.
if line_length == buffer_str.len() && line_length > 0 {
buffer_reader.consume(line_length);
continue;
} else {
// Since lines cut each \n or \n\r\n add 1 to count this char.
// TODO: count the number of \n|\r|\n chars
buffer_reader.consume(line_length + 1);
full_line.push('\n');
return Some(full_line);
}
}
// There is no more characters to read.
None => {
return Some(full_line);
}
}
}
// This is the first read
let buffer_str_len = buffer_str.len();
buffer_reader.consume(buffer_str_len);
// There is no more characters to read.
if buffer_str_len == 0 {
return None;
}
full_line.push_str(buffer_str.to_owned().as_str());
// When there is no '\n' or EOF, continue reading to find a '\n'
if !end_with_nl_or_eof(buffer_str) || buffer_str_len < BUFFER_SIZE {
continue 'outer;
} else {
return Some(full_line);
}
}
Err(err) => {
println!("bgrep: err: {}", err,);
exit(1)
}
}
}
}
fn end_with_nl_or_eof(buffer_str: String) -> bool {
(buffer_str.len() < BUFFER_SIZE) || buffer_str.chars().last().unwrap_or(' ') == '\n'
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment