While containers like Vec<Nuc> are great for interop, their Debug representations
are a bit verbose for DNA or peptides and they don’t support parsing.
Seq can wrap sufficiently Vec-like containers to provide such features.
use std::collections::VecDeque;
use nucs::{Amino, Nuc, Seq};
// `Seq` supports parsing strings. Whitespace is ignored:
let mut dna: Seq<Vec<Nuc>> = "
A
CAT
ATAC
".parse()?;
// `Seq` implements `Display`:
assert_eq!(dna.to_string(), "ACATATAC");
// If alternate formatting is used, the sequence is line-wrapped according to the width:
assert_eq!(format!("{dna:#5}"), "ACATA\nTAC");
// You can still work with the underlying collection:
dna[2..].fill(Nuc::G);
assert_eq!(dna.to_string(), "ACGGGGGG");
// Other collections than `Vec` are supported:
let mut dna = Seq(VecDeque::from_iter(dna));
dna.push_front(Nuc::T);
assert_eq!(dna.to_string(), "TACGGGGGG");
// `AmbiNuc` and `Amino` are supported as well:
let peptide: Seq<Vec<Amino>> = "INTEROP".parse()?;
assert_eq!(peptide.to_string(), "INTEROP");
Seq<T> reads from its collection via &T::into_iter, and
expects yielded items to be &impl Symbol. This means it works with Vec,
VecDeque, [T; N], and custom Vec-like
containers such as SmallVec, TinyVec, ArrayVec, etc. Unfortunately, it doesn’t
work with &[T] or Arc<[T]> because neither
&&[T] nor &Arc<[T]> are directly iterable without autoderef.
Note that parsing requires &T::into_iter to determine
what type of Symbol (e.g. Nuc vs Amino) to expect;
FromIterator cannot be relied on, because a single collection may support multiple
FromIterator implementations.