1pub mod index;
10pub mod iterators;
11
12mod array;
13mod slice;
14
15pub use array::SeqArray;
16pub use slice::SeqSlice;
17
18use crate::codec::{Codec, text};
19use crate::error::ParseBioError;
20use crate::{
21 Complement, ComplementMut, Maskable, MaskableMut, Reverse, ReverseComplement,
22 ReverseComplementMut, ReverseMut,
23};
24
25use crate::{Bs, Bv, Order};
26
27use bitvec::field::BitField;
28use bitvec::view::BitView;
29
30#[cfg(feature = "serde")]
31use serde::{Deserialize, Serialize};
32
33use core::borrow::Borrow;
34use core::hash::{Hash, Hasher};
35use core::marker::PhantomData;
36use core::ops::{Bound, Deref, RangeBounds};
37use core::str::FromStr;
38use core::{fmt, ptr, str};
39
40#[derive(Debug, PartialEq, Eq, PartialOrd, Ord)]
44#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
45#[repr(transparent)]
46pub struct Seq<A: Codec> {
47 pub(crate) _p: PhantomData<A>,
48 pub(crate) bv: Bv,
49}
50
51impl<A: Codec> From<Seq<A>> for usize {
52 fn from(seq: Seq<A>) -> usize {
53 debug_assert!(seq.bv.len() <= usize::BITS as usize);
54 if seq.bv.is_empty() {
55 0
56 } else {
57 seq.bv.load_le::<usize>() }
59 }
60}
61
62impl<A: Codec> Hash for Seq<A> {
63 fn hash<H: Hasher>(&self, state: &mut H) {
64 self.as_ref().hash(state);
65 }
67}
68
69impl<A: Codec> Default for Seq<A> {
70 fn default() -> Self {
71 Self::new()
72 }
73}
74
75impl<A: Codec> Seq<A> {
76 pub fn new() -> Self {
77 Seq {
78 _p: PhantomData,
79 bv: Bv::new(),
80 }
81 }
82
83 fn bit_range<R: RangeBounds<usize>>(&self, range: R) -> (usize, usize) {
84 let s = match range.start_bound() {
85 Bound::Included(&n) => n,
86 Bound::Excluded(&n) => n.checked_add(1).expect("bound overflow"),
87 Bound::Unbounded => 0,
88 };
89
90 let e = match range.end_bound() {
91 Bound::Included(&n) => n.checked_add(1).expect("bound overflow"),
92 Bound::Excluded(&n) => n,
93 Bound::Unbounded => self.len(),
94 };
95
96 assert!(s <= e, "Start of range must be less than or equal to end");
97 assert!(e <= self.len(), "Range out of bounds");
98
99 (s * A::BITS as usize, e * A::BITS as usize)
100 }
101
102 pub fn trim_u8(v: &[u8]) -> Result<Self, ParseBioError> {
115 let start = v
116 .iter()
117 .position(|&byte| A::try_from_ascii(byte).is_some())
118 .unwrap_or(v.len());
119
120 let end = v[start..]
121 .iter()
122 .rposition(|&byte| A::try_from_ascii(byte).is_some())
123 .map_or(start, |pos| start + pos + 1);
124
125 v[start..end]
126 .iter()
127 .map(|&byte| A::try_from_ascii(byte).ok_or(ParseBioError::UnrecognisedBase(byte)))
128 .collect()
129 }
130
131 pub fn with_capacity(len: usize) -> Self {
132 Seq {
133 _p: PhantomData,
134 bv: Bv::with_capacity(len * A::BITS as usize),
135 }
136 }
137
138 pub fn bit_and(self, rhs: Seq<A>) -> Seq<A> {
139 Seq::<A> {
140 _p: PhantomData,
141 bv: Bv::from_bitslice(&(self.bv & rhs.bv)),
142 }
143 }
144
145 pub fn bit_or(self, rhs: Seq<A>) -> Seq<A> {
146 Seq::<A> {
147 _p: PhantomData,
148 bv: Bv::from_bitslice(&(self.bv | rhs.bv)),
149 }
150 }
151
152 pub fn push(&mut self, item: A) {
153 let byte: u8 = item.to_bits();
154 self.bv
155 .extend_from_bitslice(&byte.view_bits::<Order>()[..A::BITS as usize]);
156 }
157
158 pub fn clear(&mut self) {
159 self.bv.clear();
160 }
161
162 pub fn truncate(&mut self, len: usize) {
170 self.bv.truncate(len * A::BITS as usize);
171 }
172
173 pub fn prepend(&mut self, other: &SeqSlice<A>) {
181 let mut bv = Bv::with_capacity(self.bv.len() + other.bs.len());
182 bv.extend_from_bitslice(&other.bs);
183 bv.extend_from_bitslice(&self.bv);
184 self.bv = bv;
185 }
186
187 pub fn append(&mut self, other: &SeqSlice<A>) {
195 self.bv.extend_from_bitslice(&other.bs);
196 }
197
198 pub fn splice<R: RangeBounds<usize>>(&mut self, range: R, other: &SeqSlice<A>) {
206 let (s, e) = self.bit_range(range);
207
208 let mut bv = Bv::with_capacity(self.bv.len() - (e - s) + other.bs.len());
209
210 bv.extend_from_bitslice(&self.bs[..s]);
211 bv.extend_from_bitslice(&other.bs);
212 bv.extend_from_bitslice(&self.bs[e..]);
213
214 self.bv = bv;
215 }
216
217 pub fn insert(&mut self, index: usize, other: &SeqSlice<A>) {
228 assert!(index <= self.len(), "Index out of bounds");
229
230 let i = index * A::BITS as usize;
231 let mut bv = Bv::with_capacity(self.bv.len() + other.bs.len());
232
233 bv.extend_from_bitslice(&self.bs[..i]);
234 bv.extend_from_bitslice(&other.bs);
235 bv.extend_from_bitslice(&self.bs[i..]);
236
237 self.bv = bv;
238 }
239
240 pub fn remove<R: RangeBounds<usize>>(&mut self, range: R) {
248 let (s, e) = self.bit_range(range);
249 self.bv.drain(s..e);
250 }
251
252 pub fn extend_from_iter<I: IntoIterator<Item = A>>(&mut self, iter: I) {
253 iter.into_iter().for_each(|base| self.push(base));
254 }
255
256 pub fn from_raw(len: usize, bits: &[usize]) -> Option<Self> {
264 let mut bv: Bv = Bv::from_slice(bits);
265 let bit_len = len.checked_mul(A::BITS as usize)?;
266
267 if bit_len > bv.len() {
268 return None;
269 }
270 bv.truncate(bit_len);
271 Some(Seq {
272 _p: PhantomData,
273 bv,
274 })
275 }
276
277 pub fn into_raw(&self) -> &[usize] {
286 self.bv.as_raw_slice()
287 }
288}
289
290impl<A: Codec> ReverseMut for Seq<A> {
291 fn rev(&mut self) {
292 self.bv.reverse();
293 for chunk in self.bv.rchunks_exact_mut(A::BITS as usize) {
294 chunk.reverse();
295 }
296 }
297}
298
299impl<A: Codec + ComplementMut> ComplementMut for Seq<A> {
300 fn comp(&mut self) {
301 unsafe {
302 for base in self.bv.chunks_exact_mut(A::BITS as usize).remove_alias() {
303 let mut bc = A::unsafe_from_bits(base.load_le::<u8>());
304 bc.comp();
305 base.store(bc.to_bits() as usize);
306 }
307 }
308 }
309}
310
311impl<A: Codec + MaskableMut> MaskableMut for Seq<A> {
312 fn mask(&mut self) {
313 unsafe {
314 for base in self.bv.chunks_exact_mut(A::BITS as usize).remove_alias() {
315 let mut bc = A::unsafe_from_bits(base.load_le::<u8>());
316 bc.mask();
317 base.store(bc.to_bits() as usize);
318 }
319 }
320 }
321 fn unmask(&mut self) {
322 unsafe {
323 for base in self.bv.chunks_exact_mut(A::BITS as usize).remove_alias() {
324 let mut bc = A::unsafe_from_bits(base.load_le::<u8>());
325 bc.unmask();
326 base.store(bc.to_bits() as usize);
327 }
328 }
329 }
330}
331
332impl<A: Codec + MaskableMut> Maskable for Seq<A> {}
333
334impl<A: Codec + ComplementMut> ReverseComplementMut for Seq<A> where
335 Seq<A>: ComplementMut + ReverseMut
336{
337}
338
339impl<A: Codec> Reverse for Seq<A> {}
340
341impl<A: Codec + ComplementMut> Complement for Seq<A> {}
342
343impl<A: Codec + ComplementMut> ReverseComplement for Seq<A> where Seq<A>: ComplementMut + ReverseMut {}
344
345impl<A: Codec> PartialEq<SeqSlice<A>> for Seq<A> {
346 fn eq(&self, other: &SeqSlice<A>) -> bool {
347 self.as_ref() == other
348 }
349}
350
351impl<A: Codec> PartialEq<&SeqSlice<A>> for Seq<A> {
352 fn eq(&self, other: &&SeqSlice<A>) -> bool {
353 self.as_ref() == *other
354 }
355}
356
357impl<A: Codec> PartialEq<Seq<A>> for &Seq<A> {
358 fn eq(&self, other: &Seq<A>) -> bool {
359 **self == *other
360 }
361}
362
363impl<A: Codec> PartialEq<&Seq<A>> for Seq<A> {
364 fn eq(&self, other: &&Seq<A>) -> bool {
365 *self == **other
366 }
367}
368
369impl<A: Codec> Borrow<SeqSlice<A>> for Seq<A> {
393 fn borrow(&self) -> &SeqSlice<A> {
394 self.as_ref()
395 }
396}
397
398impl<A: Codec> Borrow<SeqSlice<A>> for &Seq<A> {
399 fn borrow(&self) -> &SeqSlice<A> {
400 self.as_ref()
401 }
402}
403
404impl<A: Codec> Deref for Seq<A> {
418 type Target = SeqSlice<A>;
419
420 fn deref(&self) -> &Self::Target {
421 let bs: *const Bs = ptr::from_ref::<Bs>(&self.bv);
422 unsafe { &*(bs as *const SeqSlice<A>) }
423 }
424}
425
426impl<A: Codec> AsRef<SeqSlice<A>> for Seq<A> {
440 fn as_ref(&self) -> &SeqSlice<A> {
441 self
442 }
443}
444
445impl<A: Codec> Clone for Seq<A> {
458 fn clone(&self) -> Self {
459 Self {
460 _p: PhantomData,
461 bv: self.bv.clone(),
462 }
463 }
464}
465
466impl<A: Codec> FromIterator<A> for Seq<A> {
467 fn from_iter<I: IntoIterator<Item = A>>(iter: I) -> Self {
468 let i = iter.into_iter();
469 let mut seq = Seq::with_capacity(i.size_hint().0);
470 seq.extend(i);
471 seq
472 }
473}
474
475impl<A: Codec> From<&Vec<A>> for Seq<A> {
476 fn from(vec: &Vec<A>) -> Self {
477 vec.iter().copied().collect()
480 }
481}
482
483impl<A: Codec, B: Codec> From<&SeqSlice<A>> for Seq<B>
484where
485 A: Into<B>,
486{
487 fn from(slice: &SeqSlice<A>) -> Self {
488 slice.iter().map(Into::into).collect()
489 }
490}
491
492impl<A: Codec, B: Codec, const N: usize, const W: usize> From<&SeqArray<A, N, W>> for Seq<B>
493where
494 A: Into<B>,
495{
496 fn from(slice: &SeqArray<A, N, W>) -> Self {
497 slice.iter().map(Into::into).collect()
498 }
499}
500
501impl<A: Codec, B: Codec, const N: usize, const W: usize> From<SeqArray<A, N, W>> for Seq<B>
502where
503 A: Into<B>,
504{
505 fn from(slice: SeqArray<A, N, W>) -> Self {
506 slice.iter().map(Into::into).collect()
507 }
508}
509
510impl<A: Codec> TryFrom<&str> for Seq<A> {
511 type Error = ParseBioError;
512
513 fn try_from(s: &str) -> Result<Self, Self::Error> {
514 Seq::<A>::try_from(s.as_bytes())
515 }
516}
517
518impl<A: Codec> TryFrom<String> for Seq<A> {
519 type Error = ParseBioError;
520
521 fn try_from(s: String) -> Result<Self, Self::Error> {
522 Seq::<A>::try_from(s.as_str())
523 }
524}
525
526impl<A: Codec> TryFrom<&String> for Seq<A> {
527 type Error = ParseBioError;
528
529 fn try_from(s: &String) -> Result<Self, Self::Error> {
530 Seq::<A>::try_from(s.as_str())
531 }
532}
533
534impl<A: Codec> FromStr for Seq<A> {
535 type Err = ParseBioError;
536
537 fn from_str(s: &str) -> Result<Self, Self::Err> {
538 Seq::<A>::try_from(s)
539 }
540}
541
542impl<A: Codec> TryFrom<&[u8]> for Seq<A> {
543 type Error = ParseBioError;
544
545 fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
546 v.iter()
547 .copied()
548 .map(|byte| A::try_from_ascii(byte).ok_or(ParseBioError::UnrecognisedBase(byte)))
549 .collect()
550 }
551}
552
553impl<A: Codec> TryFrom<Vec<u8>> for Seq<A> {
554 type Error = ParseBioError;
555
556 fn try_from(v: Vec<u8>) -> Result<Self, Self::Error> {
557 v.into_iter()
561 .map(|byte| A::try_from_ascii(byte).ok_or(ParseBioError::UnrecognisedBase(byte)))
562 .collect()
563 }
564}
565
566impl<A: Codec> From<Seq<A>> for String {
567 fn from(seq: Seq<A>) -> Self {
568 String::from(seq.as_ref())
569 }
570}
571
572impl<A: Codec> From<&Seq<A>> for String {
573 fn from(seq: &Seq<A>) -> Self {
574 String::from(seq.as_ref())
575 }
576}
577
578impl<A: Codec> fmt::Display for Seq<A> {
579 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
580 fmt::Display::fmt(self.as_ref(), f)
581 }
582}
583
584impl<A: Codec> Extend<A> for Seq<A> {
585 fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
586 self.extend_from_iter(iter);
587 }
588}
589
590impl From<Vec<usize>> for Seq<text::Dna> {
591 fn from(vec: Vec<usize>) -> Self {
592 Seq {
593 _p: PhantomData,
594 bv: Bv::from_vec(vec),
595 }
596 }
597}
598
599impl<A: Codec> From<&Bs> for Seq<A> {
601 fn from(bs: &Bs) -> Self {
602 Seq {
603 _p: PhantomData,
604 bv: bs.into(),
605 }
606 }
607}
608
609impl<A: Codec> From<Bv> for Seq<A> {
611 fn from(bv: Bv) -> Self {
612 Seq {
613 _p: PhantomData,
614 bv,
615 }
616 }
617}
618
619#[cfg(test)]
620mod tests {
621 use crate::codec::text;
622 use crate::prelude::*;
623 use crate::{Bv, Order};
624 use bitvec::prelude::*;
625 use core::borrow::Borrow;
626 use core::hash::{Hash, Hasher};
627 use core::marker::PhantomData;
628 use std::collections::hash_map::DefaultHasher;
629
630 #[test]
631 fn test_revcomp() {
632 let s1: Seq<Dna> = dna!("ATGTGTGCGACTGA").into();
633 let mut s2: Seq<Dna> = dna!("TCAGTCGCACACAT").into();
634 let s3: &SeqSlice<Dna> = &s1;
635
636 assert_eq!(s3.to_revcomp(), s2.to_revcomp().to_revcomp());
637 assert_eq!(s3.to_revcomp(), &s2);
638
639 s2.revcomp();
640
641 assert_eq!(s3.to_revcomp(), s2.to_revcomp());
642 assert_ne!(s3, s2.to_revcomp());
643 }
644
645 #[test]
646 fn test_revcomp_mismatched_sizes() {
647 let s1 = dna!("AAAA");
648 let mut s2: Seq<Dna> = dna!("TTTTT").into();
649 s2.revcomp();
650 assert_ne!(s1, s2);
651 }
652
653 #[test]
654 fn test_revcomp_idempotence() {
655 let mut s = dna!("AAACGCTACGTACGCGCCTTCGGGGCATCAGCACCAC").to_owned();
656 let sc = dna!("AAACGCTACGTACGCGCCTTCGGGGCATCAGCACCAC");
657 s.revcomp();
658 assert_eq!(s.to_revcomp(), sc);
659 s.comp();
660 s.rev();
661 s.rev();
662 s.comp();
663 assert_eq!(s.to_revcomp(), sc);
664 }
665 #[test]
666 fn slice_index_comparisions() {
667 let s1 = dna!("ATGTGTGCGACTGATGATCAAACGTAGCTACG");
668 let s2 = dna!("ACGTGTGTGCTAGCTAATCGATCAAAAAG");
669
670 assert_eq!(&s1[0], &s2[0]);
671 assert_ne!(&s1[1], &s2[1]);
672 assert_eq!(&s1[2..4], &s2[2..4]);
673 assert_eq!(&s1[15..21], &s2[19..25]);
674 assert_ne!(&s1[2..20], &s2[2..20]);
675 }
676
677 #[test]
678 #[allow(clippy::redundant_slicing)]
679 fn slice_index_owned() {
680 let seq = dna!("GCTCGATCACT");
681
682 assert_eq!(&seq[..], dna!("GCTCGATCACT"));
683 assert_eq!(&seq[..=4], dna!("GCTCG"));
684 assert_eq!(&seq[1..=4], dna!("CTCG"));
685 assert_eq!(&seq[1..4], dna!("CTC"));
686 assert_eq!(&seq[..4], dna!("GCTC"));
687 assert_eq!(&seq[1..], dna!("CTCGATCACT"));
688 }
689
690 #[test]
691 #[allow(clippy::redundant_slicing)]
692 fn slice_indexing() {
693 let seq = dna!("TGCATCGAT");
694
695 assert_ne!(&seq[..], &dna!("AGCATCGAA")[..]);
696 assert_ne!(&seq[3..=6], &dna!("ATC")[..]);
697 assert_ne!(&seq[..=6], &dna!("TGCATC")[..]);
698 assert_ne!(&seq[4..5], &dna!("TC")[..]);
699 assert_ne!(&seq[..6], &dna!("TGCAT")[..]);
700 assert_ne!(&seq[5..], &dna!("TCGAT")[..]);
701
702 assert_eq!(&seq[..], &dna!("TGCATCGAT")[..]);
703 assert_eq!(&seq[3..=6], &dna!("ATCG")[..]);
704 assert_eq!(&seq[..=6], &dna!("TGCATCG")[..]);
705 assert_eq!(&seq[4..5], &dna!("T")[..]);
706 assert_eq!(&seq[..6], &dna!("TGCATC")[..]);
707 assert_eq!(&seq[5..], &dna!("CGAT")[..]);
708 }
709
710 #[test]
711 #[allow(clippy::redundant_slicing)]
712 fn slice_index_ranges() {
713 let s1: &'static SeqSlice<Dna> = dna!("ACGACTGATCGA");
714 let s2: &'static SeqSlice<Dna> = dna!("TCGAACGACTGA");
715
716 assert_eq!(&s1[..8], &s2[4..]);
717 assert_eq!(&s1[8..], &s2[..4]);
718 assert_ne!(&s1[8..], &s2[8..]);
719 assert_ne!(&s1[..], &s2[..4]);
720
721 assert_eq!(&s1[..=7], &s2[4..]);
722 assert_eq!(&s1[8..], &s2[..=3]);
723 assert_ne!(&s1[8..11], &s2[8..=11]);
724 assert_ne!(&s1[..], &s2[..=4]);
725 }
726
727 #[test]
728 fn slice_nth() {
729 let s = dna!("ATGTGTGCGACTGATGATCAAACGTAGCTACG");
730
731 assert_eq!(s.nth(0), Dna::A);
732 assert_ne!(s.nth(0), Dna::G);
733
734 assert_eq!(s.nth(1), Dna::T);
735 assert_ne!(s.nth(1), Dna::C);
736
737 assert_eq!(s.nth(s.len() - 1), Dna::G);
738 assert_ne!(s.nth(s.len() - 1), Dna::C);
739 }
740
741 #[test]
742 #[allow(clippy::redundant_slicing)]
743 fn slice_rangeto_and_full() {
744 let s1 = dna!("ATCGACTAGCATGCTACG");
745 let s2 = dna!("ATCGACTAG");
746
747 assert_eq!(&s1[..s2.len()], &s2[..]);
748 assert_ne!(&s2[..s2.len()], &s1[..]);
749 }
750
751 #[test]
752 fn from_slice() {
753 let s1 = dna!("ATGTGTGCGACTGATGATCAAACGTAGCTACG");
754 let s: &SeqSlice<Dna> = &s1[15..21];
755 assert_eq!(format!("{s}"), "GATCAA");
756 }
757
758 #[test]
759 fn string_to_seq() {
760 let seq_str = "ACTGACTG";
761 let seq: Result<Seq<Dna>, _> = seq_str.try_into();
762 assert!(seq.is_ok());
763 assert_eq!(seq.unwrap().to_string(), seq_str);
764 }
765
766 #[test]
767 fn invalid_string_to_seq() {
768 let invalid_seq_str = "ACUGACTG";
769 let seq: Result<Seq<Dna>, _> = invalid_seq_str.try_into();
770 assert!(seq.is_err());
771 }
772
773 #[test]
774 fn seq_to_string() {
775 let seq_str = "ACTGACTG";
776 let seq: Seq<Dna> = seq_str.try_into().unwrap();
777 let result_str: String = seq.into();
778 assert_eq!(result_str, seq_str);
779 }
780
781 #[test]
782 fn seqslice_to_string() {
783 let seq_str = "ACTGACTG";
784 let seq: Seq<Dna> = seq_str.try_into().unwrap();
785 let slice = &seq[1..5];
786 let result_str: String = slice.into();
787 assert_eq!(result_str, "CTGA");
788 }
789
790 #[test]
791 #[should_panic(expected = "range 2..18 out of bounds: 16")]
792 fn invalid_seqslice_to_string() {
793 let seq_str = "ACTGACTG";
794 let seq: Seq<Dna> = seq_str.try_into().unwrap();
795 let _ = &seq[1..9];
796 }
797
798 #[test]
799 fn test_push() {
800 let mut seq = Seq::<Dna>::new();
801 seq.push(Dna::A);
802 seq.push(Dna::C);
803 seq.push(Dna::G);
804 seq.push(Dna::T);
805
806 assert_eq!(seq.len(), 4);
807 assert_eq!(String::from(seq), "ACGT");
808 }
809
810 #[test]
811 fn test_extend_amino() {
812 let mut seq = Seq::<Amino>::new();
813 seq.push(Amino::S);
814 seq.push(Amino::L);
815
816 seq.extend(vec![Amino::Y, Amino::M]);
817
818 assert_eq!(seq.len(), 4);
819 assert_eq!(String::from(seq), "SLYM");
820 }
821 #[test]
822 fn test_extend() {
823 let mut seq = Seq::<Dna>::new();
824 seq.push(Dna::A);
825 seq.push(Dna::C);
826
827 seq.extend(vec![Dna::G, Dna::T]);
828
829 assert_eq!(seq.len(), 4);
830 assert_eq!(String::from(seq), "ACGT");
831 }
832
833 #[test]
834 fn test_eqs() {
835 let seq: Seq<Dna> = "ACTAGCATCGA".try_into().unwrap();
836 let seq2: Seq<Dna> = "ACTAGCATCGA".try_into().unwrap();
837 let slice: &SeqSlice<Dna> = &seq;
838 let slice2: &SeqSlice<Dna> = &seq2[..];
839 assert_eq!(seq, slice);
840 assert_eq!(seq2, slice);
841 assert_eq!(seq2, slice2);
842 assert_eq!(slice, slice2);
843 assert_eq!(seq, seq2);
844 }
845
846 #[test]
847 fn test_str_eqs() {
848 let string: String = "ACTAGCATCGA".into();
849 let slice: &str = "GCTGCATCGATC";
850
851 let seq1: Seq<Dna> = Seq::<Dna>::try_from(slice).unwrap();
852 let seq2: Seq<Dna> = Seq::<Dna>::try_from(string.clone()).unwrap();
853
854 assert_eq!(seq2.to_string(), string);
855 assert_eq!(seq1.to_string(), slice);
856
857 assert_ne!(seq2.to_string(), slice);
858 assert_ne!(seq1.to_string(), string);
859 }
860
861 #[test]
862 fn test_from_iter() {
863 let iter = vec![Dna::A, Dna::C, Dna::G, Dna::T].into_iter();
864 let seq: Seq<Dna> = Seq::from_iter(iter);
865
866 assert_eq!(seq.len(), 4);
867 assert_eq!(String::from(seq), "ACGT");
868 }
869
870 #[test]
871 fn test_bit_order() {
872 let raw: usize = 0b10_11_01_11_10_01_00_01;
873 let mut bv: Bv = BitVec::default();
874 bv.extend(&raw.view_bits::<Order>()[..(Dna::BITS as usize * 8)]);
875 let s = Seq::<Dna> {
876 bv,
877 _p: PhantomData,
878 };
879 assert_eq!(dna!("CACGTCTG").to_string(), "CACGTCTG");
880 assert_eq!(String::from(s), "CACGTCTG");
881 }
883
884 #[test]
885 fn test_borrow() {
886 let seq: Seq<Dna> = dna!("ACGACCCCCATAGATGGGCTG").into();
887 let slice: &SeqSlice<Dna> = seq.borrow();
888 assert_eq!(slice, &seq[..]);
889 assert_ne!(slice, &seq[1..]);
890 }
891
892 #[test]
893 #[allow(clippy::explicit_auto_deref)]
894 fn test_deref() {
895 let seq: Seq<Dna> = dna!("AGAATGATCG").into();
896 let slice: &SeqSlice<Dna> = &*seq;
897
898 assert_eq!(slice, &seq[..]);
899 assert_ne!(slice, &seq[1..]);
900 }
901
902 #[test]
903 fn test_asref() {
904 let seq: Seq<Dna> = dna!("AGAATGATCAAAATATATATAAAG").into();
905 let slice: &SeqSlice<Dna> = seq.as_ref();
906 assert_ne!(slice, &seq[2..5]);
907 assert_eq!(slice, &seq[..]);
908 }
909
910 #[test]
911 fn test_to_owned() {
912 let seq: Seq<Dna> = dna!("AGAATGAATCG").into();
913 let slice: &SeqSlice<Dna> = &seq;
914 let owned: Seq<Dna> = slice[2..5].to_owned();
915 assert_eq!(&owned, &seq[2..5]);
916 assert_eq!(owned, seq[2..5].to_owned());
917 assert_ne!(&owned, &seq[..]);
918 }
919
920 #[test]
921 fn test_clone() {
922 let seq: Seq<Dna> = dna!("AGAATGATGGGGGGGGGGGCG").into();
923 let cloned = seq.clone();
924 assert_eq!(seq, cloned);
925 }
926 #[test]
927 fn test_trim() {
928 let seq = b"AGAATGATGGGGGGGGGGGCG";
929 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
930 assert_eq!(s, dna!("AGAATGATGGGGGGGGGGGCG"));
931
932 let seq = b"NNNNAGAATGATGGGGGGGGGGGCGNNNNNNNNNNN";
933 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
934 assert_eq!(s, dna!("AGAATGATGGGGGGGGGGGCG"));
935
936 let seq = b"NNNNAGAATGATGGGGNGGGGGGGCGNNNNNNNNNNN";
937 let s: Result<Seq<Dna>, ParseBioError> = Seq::trim_u8(seq);
938 assert_eq!(s, Err(ParseBioError::UnrecognisedBase(b'N')));
939
940 let seq = b"AGAATGATGGGGGGGGGGGCG";
941 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
942 assert_eq!(s, dna!("AGAATGATGGGGGGGGGGGCG"));
943
944 let seq = b"NNNNAGAATGATGGGGGGGGGGGCGNNNNNNNNNNN";
945 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
946 assert_eq!(s, dna!("AGAATGATGGGGGGGGGGGCG"));
947
948 let seq = b"NNNNAGAATGATGGGGNGGGGGGGCGNNNNNNNNNNN";
949 let s: Result<Seq<Dna>, ParseBioError> = Seq::trim_u8(seq);
950 assert_eq!(s, Err(ParseBioError::UnrecognisedBase(b'N')));
951
952 let seq = b"";
953 let s: Result<Seq<Dna>, ParseBioError> = Seq::trim_u8(seq);
954 assert!(s.is_ok());
955 assert_eq!(s.unwrap(), dna!(""));
956
957 let seq = b"XXXX";
958 let s: Result<Seq<Dna>, ParseBioError> = Seq::trim_u8(seq);
959 assert!(s.is_ok());
960 assert_eq!(s.unwrap(), dna!(""));
961
962 let seq = b"XXACGT";
963 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
964 assert_eq!(s, dna!("ACGT"));
965
966 let seq = b"ACGTXX";
967 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
968 assert_eq!(s, dna!("ACGT"));
969
970 let seq = b"ACGTACGTACGTACGTACGTACGT";
971 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
972 assert_eq!(s, dna!("ACGTACGTACGTACGTACGTACGT"));
973
974 let seq = b"XXACGTXXACGTXX";
975 let s: Result<Seq<Dna>, ParseBioError> = Seq::trim_u8(seq);
976 assert_eq!(s, Err(ParseBioError::UnrecognisedBase(b'X')));
977
978 let seq = b"A";
979 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
980 assert_eq!(s, dna!("A"));
981
982 let seq = b"X";
983 let s: Result<Seq<Dna>, ParseBioError> = Seq::trim_u8(seq);
984 assert!(s.is_ok());
985 assert_eq!(s.unwrap(), dna!(""));
986
987 }
1001
1002 #[test]
1003 fn test_seq_eq_and_hash() {
1004 let seq1: Seq<Dna> = "ACGT".try_into().unwrap();
1005 let seq2: Seq<Dna> = "ACGT".try_into().unwrap();
1006
1007 assert_eq!(seq1, seq2);
1009
1010 let mut hasher1 = DefaultHasher::new();
1012 seq1.hash(&mut hasher1);
1013 let hash1 = hasher1.finish();
1014
1015 let mut hasher2 = DefaultHasher::new();
1016 seq2.hash(&mut hasher2);
1017 let hash2 = hasher2.finish();
1018
1019 assert_eq!(hash1, hash2);
1020
1021 assert_eq!(record(&seq1), [4, 0, 0, 0, 0, 0, 0, 0, 0xe4]);
1022 }
1023
1024 #[test]
1025 #[allow(clippy::similar_names)]
1026 fn test_seq_slice_eq() {
1027 let seq1: Seq<Dna> = "ACGTAAAAAAAAAAAAACGTAAAACCCCGGGGTTTTA".try_into().unwrap();
1028 let seq2: Seq<Dna> = "ACGTAAAAAAAAAAAAACGTAAAACCCCGGGGTTTTAA".try_into().unwrap();
1029
1030 let slice1a: &SeqSlice<Dna> = &seq1[..];
1031 let slice1b: &SeqSlice<Dna> = &seq1[..];
1032 let slice2a: &SeqSlice<Dna> = &seq2[..seq2.len() - 1];
1033 let slice2b: &SeqSlice<Dna> = &seq2[..seq2.len() - 1];
1034
1035 let seq3: Seq<Dna> = slice2b.into();
1036
1037 assert_eq!(slice1a, slice2b);
1038 assert_eq!(&slice2a, &slice2b);
1039 assert_eq!(seq1, slice2a);
1040 assert_eq!(slice1b, seq3);
1041 assert_eq!(slice1a, slice1b);
1042 assert_eq!(seq1, seq3);
1043
1044 assert_ne!(seq1, seq2);
1045 assert_ne!(seq2, seq3);
1046 assert_ne!(seq2, slice2a);
1047 assert_ne!(seq2, slice1b);
1048
1049 assert_eq!(&slice1a, &slice1b);
1050
1051 assert_eq!(seq1, &seq1);
1052
1053 assert_eq!(seq1, &seq3);
1054 assert_eq!(&seq1, seq3);
1055 assert_eq!(&seq1, &seq3);
1056
1057 assert_eq!(slice1a, seq3);
1058 assert_eq!(seq1, slice2a);
1061 assert_eq!(&seq1, slice2a);
1062 assert_eq!(&seq1, slice2a);
1065 }
1066 #[test]
1067 fn test_seq_slice_hash() {
1068 let seq1: Seq<Dna> = "ACGTAAAAAAAAAAAAACGTAAAACCCCGGGGAAAAA".try_into().unwrap();
1069 let seq2: Seq<Dna> = "ACGTAAAAAAAAAAAAACGTAAAACCCCGGGGAAAAA".try_into().unwrap();
1070
1071 let seq3: Seq<Dna> = "ACGTAAAAAAAAAAAAACGTAAAACCCCGGGG".try_into().unwrap();
1072
1073 let slice1 = &seq1[..];
1074 let slice2 = &seq2[..];
1075
1076 let slice3 = &seq3[..];
1077
1078 let slice1_32 = &seq1[..32];
1079
1080 let mut hasher1 = DefaultHasher::new();
1081 seq1.hash(&mut hasher1);
1082 let full1 = hasher1.finish();
1083
1084 let mut hasher1a = DefaultHasher::new();
1085 seq1.hash(&mut hasher1a);
1086 let full1_alt = hasher1a.finish();
1087
1088 let mut hasher2 = DefaultHasher::new();
1089 seq2.hash(&mut hasher2);
1090 let full2 = hasher2.finish();
1091
1092 let mut hasher3 = DefaultHasher::new();
1093 slice1.hash(&mut hasher3);
1094 let full1_slice = hasher3.finish();
1095
1096 let mut hasher4 = DefaultHasher::new();
1097 slice2.hash(&mut hasher4);
1098 let full2_slice = hasher4.finish();
1099
1100 let mut hasher5 = DefaultHasher::new();
1101 slice3.hash(&mut hasher5);
1102 let short1_slice = hasher5.finish();
1103
1104 let mut hasher6 = DefaultHasher::new();
1105 slice1_32.hash(&mut hasher6);
1106 let seq1_short = hasher6.finish();
1107
1108 assert_eq!(full1, full1_alt);
1109 assert_eq!(full1, full2);
1110 assert_ne!(full2_slice, short1_slice);
1111 assert_eq!(full2, full1_slice);
1112 assert_eq!(short1_slice, seq1_short);
1113 assert_ne!(seq1_short, full1_slice);
1114
1115 assert_ne!(full1, short1_slice);
1116 }
1117
1118 #[test]
1119 fn test_fromstr() {
1120 let seq: Result<Seq<Dna>, ParseBioError> =
1121 "ACGATGAGTAGTCGCCATCGTATCTTTGACTGCCGATGCTA".parse();
1122 assert!(seq.is_ok());
1123
1124 let seq: Result<Seq<Dna>, ParseBioError> =
1125 "ACGATGAGTAGBCGCCATCGTATCTTTGACTGCCGATGCTA".parse();
1126 assert_eq!(seq, Err(ParseBioError::UnrecognisedBase(b'B')));
1127 }
1128
1129 #[test]
1130 fn test_lens() {
1131 assert_eq!(iupac!("AWANWATNA---SKAGTCAA").len(), 20);
1132 }
1133
1134 #[test]
1135 fn test_unique_bitarray_ident() {
1136 let s1 = dna!(
1137 "ATCGACTACGATCGCTACGATCGATCGATCGATCGAATCTCCCGCGCGATCATCGATCATCGCTACGTACGTCGAAAAATATAATGGG"
1138 );
1139 let s2 = dna!(
1140 "ATCGACTACGATCGCTACGATCGATCGATCGATCGAATCTCCCGCGCGATCATCGATCATCGCTACGTACGTCGAAAAATATAATGGG"
1141 );
1142
1143 let s3 = dna!(
1145 "CTCGACTACGATCGCTACGATCGATCGATCGATCGAATCTCCCGCGCGATCATCGATCATCGCTACGTACGTCGAAAAATATAATGGG"
1146 );
1147
1148 let s4 = dna!(
1150 "ATCGACTACGATCGCTACGATCGATCGATCGATCGAATCTCCCGCGCGATCATCGATCATCGCTACGTACGTCGAAAAATATAATGGGA"
1151 );
1152
1153 let s5 = dna!(
1155 "ATCGACTACGATCGCTACGATCGATCGATCGATCGAATCTCCCGCGCGATCATCGATCATCGCTACGTACGTCGAAAAATATAATGGC"
1156 );
1157
1158 assert_eq!(s1, s2);
1159 assert_ne!(s1, s3);
1160
1161 assert_ne!(s1.len(), s4.len());
1163 assert_ne!(s4.len(), s1.len());
1164
1165 assert_ne!(s5, s1);
1166 }
1167
1168 #[test]
1169 fn test_static() {
1170 use crate::seq::SeqArray;
1171
1172 static B: SeqArray<Dna, 5, 1> = SeqArray {
1173 _p: PhantomData,
1174 ba: bitarr![const usize, Lsb0; 1,1,0,1,0,0,1,0,1,1],
1175 };
1176
1177 let s: &'static SeqSlice<Dna> = &B;
1178
1179 let x: &'static str = "TGACT";
1180
1181 assert_eq!(s.to_string(), x);
1182 }
1183
1184 #[test]
1185 fn test_to_from_raw() {
1186 let s = "TCAGCTAGCTACGACTGATCGATCGACTGATGCCGCGCGCGGCGCCGCGCGCGCGCGCCGCGCGCCCCGCGCGCGGCGCGCGCCGCGCGCGCGCGCGGCGCGCGCGCGCGCGCGCGCGCGCGCGCGCGCGC";
1187
1188 let seq: Seq<Dna> = s.try_into().unwrap();
1189 let raw = seq.into_raw();
1190 let new = Seq::<Dna>::from_raw(s.len(), raw);
1191 assert_eq!(new.unwrap(), seq);
1192
1193 let bad = Seq::<Dna>::from_raw(s.len() + 1, raw);
1194 assert_ne!(bad.unwrap(), seq);
1195
1196 let bad = Seq::<Dna>::from_raw(342, raw);
1197 assert_eq!(bad, None);
1198 }
1199 #[test]
1200 fn test_seq_and_seq_slice_eq_and_hash() {
1201 let seq: Seq<text::Dna> = Seq::try_from("ACGT".to_string()).unwrap();
1202 let slice = &seq[..];
1203
1204 assert_eq!(seq, slice);
1206 assert_eq!(&seq, slice);
1207 assert_eq!(slice, &seq);
1208
1209 let mut hasher1 = std::collections::hash_map::DefaultHasher::new();
1211 seq.hash(&mut hasher1);
1212 let hash1 = hasher1.finish();
1213
1214 let mut hasher2 = std::collections::hash_map::DefaultHasher::new();
1215 slice.hash(&mut hasher2);
1216 let hash2 = hasher2.finish();
1217
1218 assert_eq!(hash1, hash2);
1219 }
1220
1221 #[derive(Default)]
1222 struct RecordingHasher(Vec<u8>);
1223
1224 impl Hasher for RecordingHasher {
1225 fn finish(&self) -> u64 {
1226 0
1227 }
1228 fn write(&mut self, bytes: &[u8]) {
1229 self.0.extend_from_slice(bytes);
1230 }
1231 }
1232
1233 fn record<T: Hash>(value: &T) -> Vec<u8> {
1234 let mut h = RecordingHasher::default();
1235 value.hash(&mut h);
1236 h.0
1237 }
1238
1239 #[test]
1240 fn test_hash_byte_stream_invariants() {
1241 fn check<A: Codec>(s: &str) {
1246 let seq: Seq<A> = s.try_into().unwrap_or_else(|_| panic!("parse {s:?}"));
1247 let bytes = record(&seq);
1248 assert_eq!(record::<&SeqSlice<A>>(&&seq[..]), bytes);
1249
1250 let n = seq.len();
1252 let body = (n * A::BITS as usize).div_ceil(8);
1253 assert_eq!(bytes.len(), 8 + body);
1254 assert_eq!(&bytes[..8], &(n as u64).to_le_bytes());
1255 }
1256 check::<Dna>("A");
1257 check::<Dna>("ACGT");
1258 check::<Dna>("ACGTA");
1259 check::<Dna>(&"ACGT".repeat(80)); check::<Iupac>("AC");
1261 check::<Iupac>("ACG");
1262 check::<Iupac>("NRYKBDHV");
1263 check::<Amino>("MWLLP"); check::<text::Dna>("ACGT"); }
1266
1267 #[test]
1268 fn test_kmer_hash_independent_of_storage_width() {
1269 let seq: Seq<Dna> = "ACGTACGTAC".try_into().unwrap();
1270 let slice: &SeqSlice<Dna> = &seq[..];
1271 let bytes = record(&slice);
1272 let km_usize: Kmer<Dna, 10, usize> = slice.try_into().unwrap();
1273 let km_u64: Kmer<Dna, 10, u64> = slice.try_into().unwrap();
1274 let km_u128: Kmer<Dna, 10, u128> = slice.try_into().unwrap();
1275 assert_eq!(record(&km_usize), bytes);
1276 assert_eq!(record(&km_u64), bytes);
1277 assert_eq!(record(&km_u128), bytes);
1278 }
1279
1280 #[test]
1281 fn test_prepend() {
1282 let mut seq1 =
1283 Seq::<Dna>::from_str("GCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAAT").unwrap();
1284 seq1.prepend(dna!("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
1285 assert_eq!(
1286 seq1.to_string(),
1287 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAAT"
1288 );
1289
1290 let mut seq2 =
1291 Seq::<Dna>::from_str("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").unwrap();
1292 seq2.prepend(dna!("GCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAAT"));
1293 assert_eq!(
1294 seq2.to_string(),
1295 "GCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
1296 );
1297
1298 assert_ne!(seq1, seq2);
1299 }
1300
1301 #[test]
1302 fn test_append() {
1303 let mut seq1 =
1304 Seq::<Dna>::from_str("GCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAAT").unwrap();
1305 seq1.append(dna!("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
1306 assert_eq!(
1307 seq1.to_string(),
1308 "GCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
1309 );
1310
1311 let mut seq2 =
1312 Seq::<Dna>::from_str("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").unwrap();
1313 seq2.append(dna!("GCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAAT"));
1314 assert_eq!(
1315 seq2.to_string(),
1316 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAAT"
1317 );
1318
1319 assert_ne!(seq1, seq2);
1320 }
1321
1322 #[test]
1323 fn test_remove() {
1324 let mut seq: Seq<Dna> = dna!("TCAGCATCGATCAATCG").into();
1325 seq.remove(4..6);
1326 assert_eq!(&seq, dna!("TCAGTCGATCAATCG"));
1327 seq.remove(..4);
1328 assert_eq!(&seq, dna!("TCGATCAATCG"));
1329 seq.remove(6..);
1330 assert_eq!(&seq, dna!("TCGATC"));
1331 }
1332
1333 #[test]
1334 fn test_insert() {
1335 let mut seq: Seq<Dna> = dna!("TCAGCATCGATCAATCG").into();
1336 let insertion = dna!("CCCCC");
1337
1338 seq.insert(4, insertion);
1339 assert_eq!(&seq, dna!("TCAGCCCCCCATCGATCAATCG"));
1340
1341 seq.insert(seq.len(), dna!("AAAAA"));
1342 assert_eq!(&seq, dna!("TCAGCCCCCCATCGATCAATCGAAAAA"));
1343 }
1344
1345 #[test]
1346 fn test_truncate() {
1347 let mut seq: Seq<Dna> = dna!("TCAGCATCGATCAATCG").into();
1348
1349 seq.truncate(seq.len());
1350 assert_eq!(&seq, dna!("TCAGCATCGATCAATCG"));
1351
1352 seq.truncate(10);
1353 assert_eq!(&seq, dna!("TCAGCATCGA"));
1354
1355 seq.truncate(0);
1356 assert_eq!(&seq, dna!(""));
1357 }
1358
1359 #[test]
1360 fn test_long_splice() {
1361 let mut seq: Seq<Dna> = dna!("TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT").into();
1362 let insertion = dna!("CCCCCCC");
1363
1364 seq.splice(32..38, insertion);
1365 assert_eq!(
1366 &seq,
1367 dna!("TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTCCCCCCCTTTTTTTTTTT")
1368 );
1369
1370 seq.splice(1..=1, dna!("AAA"));
1371 assert_eq!(
1372 &seq,
1373 dna!("TAAATTTTTTTTTTTTTTTTTTTTTTTTTTTTTTCCCCCCCTTTTTTTTTTT")
1374 );
1375
1376 seq.splice(10.., dna!("GGGG"));
1377 assert_eq!(&seq, dna!("TAAATTTTTTGGGG"));
1378 }
1379
1380 #[test]
1381 fn test_splice() {
1382 let mut seq: Seq<Dna> = dna!("TCAGCATCGATCAATCGT").into();
1383 let insertion = dna!("CCCCC");
1384
1385 seq.splice(4..6, insertion);
1386 assert_eq!(&seq, dna!("TCAGCCCCCTCGATCAATCGT"));
1387
1388 seq.splice(1..=1, dna!("AAA"));
1389 assert_eq!(&seq, dna!("TAAAAGCCCCCTCGATCAATCGT"));
1390
1391 seq.splice(10.., dna!("TTTT"));
1392 assert_eq!(&seq, dna!("TAAAAGCCCCTTTT"));
1393 }
1394}