use std::io::Write;
use crate::PseudoAln;
type E = Box<dyn std::error::Error>;
pub fn format_ahda_tsv_line<W: Write>(
aln: &PseudoAln,
n_targets: usize,
conn: &mut W,
) -> Result<(), E> {
let separator: char = '\t';
let mut formatted: String = String::new();
if let Some(q_id) = &aln.query_id {
formatted += &q_id.to_string();
formatted += "\t";
} else {
return Err(Box::new(crate::errors::PseudoAlnQueryIdIsEmpty{}))
};
if let Some(q_name) = &aln.query_name {
formatted += &String::from_utf8(q_name.clone())?;
} else {
return Err(Box::new(crate::errors::PseudoAlnQueryIdIsEmpty{}))
};
if let Some(ones) = &aln.ones {
let mut ones_bits: Vec<bool> = vec![false; n_targets];
ones.iter().for_each(|is_set_idx| ones_bits[*is_set_idx as usize] = true);
ones_bits.iter().for_each(|is_set| {
formatted += &separator.to_string();
formatted += &(*is_set as u32).to_string();
});
formatted += "\n";
} else {
return Err(Box::new(crate::errors::PseudoAlnOnesIsEmpty{}))
}
conn.write_all(formatted.as_bytes())?;
Ok(())
}
pub fn format_ahda_tsv_header<W: Write>(
targets: &[Vec<u8>],
conn: &mut W,
) -> Result<(), E> {
let separator: char = '\t';
let mut formatted: String = String::new();
if targets.is_empty() {
return Err(Box::new(crate::errors::AhdaTSVPrinterError{}))
}
formatted += "query_index\tquery_name";
targets.iter().for_each(|target| {
formatted += &separator.to_string();
formatted += &target.iter().map(|x| *x as char).collect::<String>();
});
formatted += "\n";
conn.write_all(formatted.as_bytes())?;
Ok(())
}
#[cfg(test)]
mod tests {
#[test]
fn format_ahda_tsv_line_1st_aligned() {
use crate::PseudoAln;
use super::format_ahda_tsv_line;
let data = PseudoAln{ones_names: None, query_id: Some(2), ones: Some(vec![0]), query_name: Some("FastqQuery.3".as_bytes().to_vec()) };
let expected: Vec<u8> = b"2\tFastqQuery.3\t1\t0\n".to_vec();
let mut got: Vec<u8> = Vec::new();
format_ahda_tsv_line(&data, 2, &mut got).unwrap();
assert_eq!(got.iter().map(|x| *x as char).collect::<String>(), expected.iter().map(|x| *x as char).collect::<String>())
}
#[test]
fn format_ahda_tsv_line_2nd_aligned() {
use crate::PseudoAln;
use super::format_ahda_tsv_line;
let data = PseudoAln{ones_names: None, query_id: Some(2), ones: Some(vec![1]), query_name: Some("FastqQuery.3".as_bytes().to_vec()) };
let expected: Vec<u8> = b"2\tFastqQuery.3\t0\t1\n".to_vec();
let mut got: Vec<u8> = Vec::new();
format_ahda_tsv_line(&data, 2, &mut got).unwrap();
assert_eq!(got, expected)
}
#[test]
fn format_ahda_tsv_line_both_aligned() {
use crate::PseudoAln;
use super::format_ahda_tsv_line;
let data = PseudoAln{ones_names: None, query_id: Some(2), ones: Some(vec![0, 1]), query_name: Some("FastqQuery.3".as_bytes().to_vec()) };
let expected: Vec<u8> = b"2\tFastqQuery.3\t1\t1\n".to_vec();
let mut got: Vec<u8> = Vec::new();
format_ahda_tsv_line(&data, 2, &mut got).unwrap();
assert_eq!(got, expected)
}
#[test]
fn format_ahda_tsv_line_no_alignments() {
use crate::PseudoAln;
use super::format_ahda_tsv_line;
let data = PseudoAln{ones_names: None, query_id: Some(2), ones: Some(vec![]), query_name: Some("FastqQuery.3".as_bytes().to_vec()) };
let expected: Vec<u8> = b"2\tFastqQuery.3\t0\t0\n".to_vec();
let mut got: Vec<u8> = Vec::new();
format_ahda_tsv_line(&data, 2, &mut got).unwrap();
assert_eq!(got, expected)
}
#[test]
fn format_ahda_tsv_header() {
use super::format_ahda_tsv_header;
let data = vec!["chromosome.fasta".as_bytes().to_vec(), "plasmid.fasta".as_bytes().to_vec()];
let expected: Vec<u8> = b"query_index\tquery_name\tchromosome.fasta\tplasmid.fasta\n".to_vec();
let mut got: Vec<u8> = Vec::new();
format_ahda_tsv_header(&data, &mut got).unwrap();
assert_eq!(got, expected)
}
#[test]
fn header_error_if_no_targets() {
use super::format_ahda_tsv_header;
let data: Vec<Vec<u8>> = Vec::new();
let got = format_ahda_tsv_header(&data, &mut Vec::new());
assert!(!got.is_ok());
}
#[test]
fn line_error_if_no_query_name() {
use crate::PseudoAln;
use super::format_ahda_tsv_line;
let data = PseudoAln{ones_names: None, query_name: None, ones: Some(vec![0, 3, 7, 11]), query_id: None};
let got = format_ahda_tsv_line(&data, 2, &mut Vec::new());
assert!(!got.is_ok());
}
#[test]
fn line_error_if_no_ones() {
use crate::PseudoAln;
use super::format_ahda_tsv_line;
let data = PseudoAln{ones_names: None, query_name: Some("ERR4035126.1262954".as_bytes().to_vec()), query_id: Some(128), ones: None};
let got = format_ahda_tsv_line(&data, 2, &mut Vec::new());
assert!(!got.is_ok());
}
#[test]
fn line_error_if_no_query_index() {
use crate::PseudoAln;
use super::format_ahda_tsv_line;
let data = PseudoAln{ones_names: None, query_name: Some("ERR4035126.1262954".as_bytes().to_vec()), query_id: None, ones: Some(vec![1])};
let got = format_ahda_tsv_line(&data, 2, &mut Vec::new());
assert!(!got.is_ok());
}
}