vcfkit 0.1.0

vcfkit: a simple program for vcf/bcf file manipulation
use std::{
    fs::File,
    io::{BufRead, BufReader},
    path::Path,
};

use anyhow::Result;
use rust_htslib::bcf::{header::Header, Format, Read, Reader, Writer};

pub fn concat_vcfs(list: &str, gzip: bool, out: &Option<&str>) -> Result<(), anyhow::Error> {
    let reader = BufReader::new(File::open(list)?);
    let mut list = vec![];
    for line in reader.lines().flatten() {
        list.push(line.to_string());
    }
    let bcf_reader = Reader::from_path(Path::new(list.get(0).unwrap()))?;
    let header = Header::from_template(&bcf_reader.header());

    let mut bcf_writer = if let Some(file) = out {
        Writer::from_path(file, &header, !gzip, Format::Vcf)?
    } else {
        Writer::from_stdout(&header, !gzip, Format::Vcf)?
    };
    let mut n = 0;
    for vcf in list {
        n += 1;
        let mut bcf = Reader::from_path(Path::new(&vcf))?;
        eprintln!("[info]: processing {n}th file {}", &vcf);
        for rec in bcf.records() {
            bcf_writer.write(&rec?)?;
        }
    }

    Ok(())
}

pub fn bcf2vcf(
    bcf: &Option<&str>,
    gzip: bool,
    out: &str
) -> Result<(), anyhow::Error> {
    let mut bcf_reader = if let Some(file) = bcf {
        Reader::from_path(file)? 
    } else {
        Reader::from_stdin()?   
    };
    let header = Header::from_template(&bcf_reader.header());

    let mut bcf_writer = Writer::from_path(Path::new(&out), &header, !gzip, Format::Vcf)?;
    for rec in bcf_reader.records() {
        bcf_writer.write(&rec?)?;    
    }

    Ok(())
}