mod fasta_index;
mod index_entry;
mod indexed_fasta;
pub use fasta_index::FastaIndex;
pub use index_entry::IndexEntry;
pub use indexed_fasta::IndexedFasta;
#[cfg(test)]
mod testing {
use crate::{FastaIndex, IndexedFasta};
use anyhow::Result;
const TEST_FASTA: &str = "example_data/example.fa";
const TEST_FASTA_INDEX: &str = "example_data/example.fa.fai";
#[test]
fn standard_usage() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let mut faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query("chr1", 0, 10)?;
assert_eq!(seq, b"ACCTACGATC");
let seq = faidx.query("chr2", 0, 10)?;
assert_eq!(seq, b"TTTTGATCGA");
Ok(())
}
#[test]
fn buffered_usage() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_buffer("chr1", 0, 10)?;
assert_eq!(seq, b"ACCTACGATC");
let seq = faidx.query_buffer("chr2", 0, 10)?;
assert_eq!(seq, b"TTTTGATCGA");
Ok(())
}
#[test]
fn interval_over_newline() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let mut faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query("chr1", 20, 30)?;
assert_eq!(seq, b"AGCTAGCTCA");
let seq = faidx.query("chr2", 20, 30)?;
assert_eq!(seq, b"CGCGCGGCCA");
Ok(())
}
#[test]
fn interval_over_newline_buffer() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_buffer("chr1", 20, 30)?;
assert_eq!(seq, b"AGCTAGCT\nCA");
let seq = faidx.query_buffer("chr2", 20, 30)?;
assert_eq!(seq, b"CGCGCGGC\nCA");
Ok(())
}
#[test]
fn interval_overextend_left() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let mut faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query("chr1", 130, 150);
assert!(seq.is_err());
Ok(())
}
#[test]
fn interval_overextend_right() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let mut faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query("chr1", 100, 150);
assert!(seq.is_err());
Ok(())
}
#[test]
fn interval_overextend_start_eq() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let mut faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query("chr1", 112, 113);
assert!(seq.is_err());
Ok(())
}
#[test]
fn interval_overexted_left_buffered() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_buffer("chr1", 130, 150);
assert!(seq.is_err());
Ok(())
}
#[test]
fn interval_overextend_right_buffered() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_buffer("chr1", 100, 150);
assert!(seq.is_err());
Ok(())
}
#[test]
fn interval_overextend_start_eq_buffered() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_buffer("chr1", 112, 113);
assert!(seq.is_err());
Ok(())
}
#[test]
fn interval_overextend_left_unbounded() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let mut faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_unbounded("chr1", 130, 150);
assert!(seq.is_err());
Ok(())
}
#[test]
fn interval_overextend_right_unbounded() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let mut faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_unbounded("chr1", 100, 150)?;
assert_eq!(seq.len(), 12);
Ok(())
}
#[test]
fn interval_overextend_right_unbounded_start_eq() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let mut faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_unbounded("chr1", 112, 150);
assert!(seq.is_err());
Ok(())
}
#[test]
fn interval_overextend_left_unbounded_buffered() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_buffer_unbounded("chr1", 130, 150);
assert!(seq.is_err());
Ok(())
}
#[test]
fn interval_overextend_right_unbounded_buffered() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_buffer_unbounded("chr1", 100, 150)?;
assert_eq!(seq.len(), 13);
assert_eq!(seq.iter().filter(|&&b| b == b'\n').count(), 1);
Ok(())
}
#[test]
fn interval_overextend_right_unbounded_start_eq_buffered() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_buffer_unbounded("chr1", 112, 150);
assert!(seq.is_err());
Ok(())
}
#[test]
fn missing_chr() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let mut faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query("chr3", 130, 150);
assert!(seq.is_err());
Ok(())
}
#[test]
fn missing_chr_buffered() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_buffer("chr3", 130, 150);
assert!(seq.is_err());
Ok(())
}
#[test]
fn malformed_interval() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let mut faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query("chr1", 130, 120);
assert!(seq.is_err());
Ok(())
}
#[test]
fn malformed_interval_buffered() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_buffer("chr1", 130, 120);
assert!(seq.is_err());
Ok(())
}
#[test]
fn empty_interval() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let mut faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query("chr1", 130, 130);
assert!(seq.is_err());
Ok(())
}
#[test]
fn empty_interval_buffered() -> Result<()> {
let index = FastaIndex::from_filepath(TEST_FASTA_INDEX)?;
let faidx = IndexedFasta::new(index, TEST_FASTA)?;
let seq = faidx.query_buffer("chr1", 130, 130);
assert!(seq.is_err());
Ok(())
}
}