#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct KitAdapter {
pub name: &'static str,
pub seq_r1: &'static [u8],
pub seq_r2: Option<&'static [u8]>,
}
pub const TRUSEQ: KitAdapter = KitAdapter {
name: "truseq",
seq_r1: b"AGATCGGAAGAGCACACGTCTGAACTCCAGTCA",
seq_r2: Some(b"AGATCGGAAGAGCGTCGTGTAGGGAAAGAGTGT"),
};
pub const NEXTERA: KitAdapter = KitAdapter {
name: "nextera",
seq_r1: b"CTGTCTCTTATACACATCT",
seq_r2: Some(b"CTGTCTCTTATACACATCT"),
};
pub const SMALL_RNA: KitAdapter =
KitAdapter { name: "small-rna", seq_r1: b"TGGAATTCTCGGGTGCCAAGG", seq_r2: None };
pub const AVITI: KitAdapter = KitAdapter {
name: "aviti",
seq_r1: b"ATGTCGGAAGGTGTGCAGGCTACCGCTTGTCAACT",
seq_r2: Some(b"ATGTCGGAAGGTGTCTGGTGAGCCAATC"),
};
pub const MGI: KitAdapter = KitAdapter {
name: "mgi",
seq_r1: b"AAGTCGGAGGCCAAGCGGTCTTAGGAAGACAA",
seq_r2: Some(b"AAGTCGGATCGTAGCCATGTCGTTCTGTGAGCCAAGGAGTTG"),
};
pub const ALL_KITS: &[KitAdapter] = &[TRUSEQ, NEXTERA, SMALL_RNA, AVITI, MGI];
pub fn kit_by_name(name: &str) -> Option<&'static KitAdapter> {
ALL_KITS.iter().find(|k| k.name.eq_ignore_ascii_case(name))
}
pub fn expand_kit_name(name: &str) -> Option<&'static [KitAdapter]> {
if name.eq_ignore_ascii_case("all") {
return Some(ALL_KITS);
}
if name.eq_ignore_ascii_case("dnbseq") {
return Some(std::slice::from_ref(&MGI));
}
kit_by_name(name).map(std::slice::from_ref)
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn kit_by_name_known() {
assert_eq!(kit_by_name("truseq"), Some(&TRUSEQ));
assert_eq!(kit_by_name("TRUSEQ"), Some(&TRUSEQ));
assert_eq!(kit_by_name("nextera"), Some(&NEXTERA));
assert_eq!(kit_by_name("small-rna"), Some(&SMALL_RNA));
assert_eq!(kit_by_name("aviti"), Some(&AVITI));
assert_eq!(kit_by_name("mgi"), Some(&MGI));
}
#[test]
fn kit_by_name_unknown() {
assert_eq!(kit_by_name("notakit"), None);
assert_eq!(kit_by_name("all"), None);
}
#[test]
fn expand_kit_name_all_unions_every_kit() {
let expanded = expand_kit_name("all").unwrap();
assert_eq!(expanded.len(), ALL_KITS.len());
}
#[test]
fn expand_kit_name_dnbseq_alias() {
let expanded = expand_kit_name("dnbseq").unwrap();
assert_eq!(expanded, std::slice::from_ref(&MGI));
}
#[test]
fn expand_kit_name_unknown_returns_none() {
assert_eq!(expand_kit_name("mystery"), None);
}
#[test]
fn adapters_are_uppercase_acgt_only() {
for kit in ALL_KITS {
for seq in [Some(kit.seq_r1), kit.seq_r2].into_iter().flatten() {
for &b in seq {
assert!(
matches!(b, b'A' | b'C' | b'G' | b'T'),
"kit {} has non-ACGT byte {:?} in adapter",
kit.name,
b as char,
);
}
}
}
}
}