fastxgz 0.4.0

A fasta/fastq parser for both compressed and not compressed files.
Documentation
use flate2::read::GzDecoder;

use std::{
    fs::File,
    io::{self, prelude::*},
};

enum FileType {
    GZ(io::BufReader<GzDecoder<File>>),
    NOGZ(io::BufReader<File>),
}

pub struct ResultLinesIterator {
    reader: FileType,
}

impl ResultLinesIterator {
    pub fn open(path: impl AsRef<std::path::Path>) -> io::Result<Self> {
        match path.as_ref().extension() {
            Some(ext) if ext == "gz" => {
                let file = File::open(path)?;
                let gz_decoder = GzDecoder::new(file);

                let reader = io::BufReader::new(gz_decoder);

                Ok(Self {
                    reader: FileType::GZ(reader),
                })
            }
            _ => {
                let file = File::open(path)?;
                let reader = io::BufReader::new(file);

                Ok(Self {
                    reader: FileType::NOGZ(reader),
                })
            }
        }
    }
}

impl Iterator for ResultLinesIterator {
    type Item = io::Result<Vec<u8>>;

    fn next(&mut self) -> Option<Self::Item> {
        let mut buffer = Vec::with_capacity(1024);
        let size_read = match &mut self.reader {
            FileType::GZ(x) => x.read_until(b'\n', &mut buffer),
            FileType::NOGZ(x) => x.read_until(b'\n', &mut buffer),
        };

        match size_read {
            Err(e) => Some(Err(e)),
            Ok(size) => match size {
                0 => None,
                _ => {
                    if buffer[buffer.len() - 1] == b'\n' {
                        buffer.pop();
                    }
                    Some(Ok(buffer))
                }
            },
        }
    }
}

pub struct LinesIterator<I>
where
    I: Iterator<Item = io::Result<Vec<u8>>>,
{
    lines_iterator: I,
}

impl<I> LinesIterator<I>
where
    I: Iterator<Item = io::Result<Vec<u8>>>,
{
    pub fn from(lines_iterator: I) -> Self {
        Self { lines_iterator }
    }
}

impl<I> Iterator for LinesIterator<I>
where
    I: Iterator<Item = io::Result<Vec<u8>>>,
{
    type Item = Vec<u8>;

    fn next(&mut self) -> Option<Self::Item> {
        let line_or_error = self.lines_iterator.next()?;
        let line = line_or_error.expect("A line could not be read due to an IO error.");
        Some(line)
    }
}