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(slice: Seq<A>) -> usize {
53 debug_assert!(slice.bv.len() <= usize::BITS as usize);
54 slice.bv.load_le::<usize>() }
56}
57
58impl<A: Codec> Hash for Seq<A> {
59 fn hash<H: Hasher>(&self, state: &mut H) {
60 self.as_ref().hash(state);
61 }
63}
64
65impl<A: Codec> Default for Seq<A> {
66 fn default() -> Self {
67 Self::new()
68 }
69}
70
71impl<A: Codec> Seq<A> {
72 pub fn new() -> Self {
73 Seq {
74 _p: PhantomData,
75 bv: Bv::new(),
76 }
77 }
78
79 fn bit_range<R: RangeBounds<usize>>(&self, range: R) -> (usize, usize) {
80 let s = match range.start_bound() {
81 Bound::Included(&n) => n,
82 Bound::Excluded(&n) => n + 1,
83 Bound::Unbounded => 0,
84 };
85
86 let e = match range.end_bound() {
87 Bound::Included(&n) => n + 1,
88 Bound::Excluded(&n) => n,
89 Bound::Unbounded => self.len(),
90 };
91
92 debug_assert!(s <= e, "Start of range must be less than or equal to end");
93 debug_assert!(e <= self.len(), "Range out of bounds");
94
95 (s * A::BITS as usize, e * A::BITS as usize)
96 }
97
98 pub fn trim_u8(v: &[u8]) -> Result<Self, ParseBioError> {
111 let start = v
112 .iter()
113 .position(|&byte| A::try_from_ascii(byte).is_some())
114 .unwrap_or(v.len());
115
116 let end = v[start..]
117 .iter()
118 .rposition(|&byte| A::try_from_ascii(byte).is_some())
119 .map_or(start, |pos| start + pos + 1);
120
121 v[start..end]
122 .iter()
123 .map(|&byte| A::try_from_ascii(byte).ok_or(ParseBioError::UnrecognisedBase(byte)))
124 .collect()
125 }
126
127 pub fn with_capacity(len: usize) -> Self {
128 Seq {
129 _p: PhantomData,
130 bv: Bv::with_capacity(len * A::BITS as usize),
131 }
132 }
133
134 pub fn bit_and(self, rhs: Seq<A>) -> Seq<A> {
135 Seq::<A> {
136 _p: PhantomData,
137 bv: Bv::from_bitslice(&(self.bv & rhs.bv)),
138 }
139 }
140
141 pub fn bit_or(self, rhs: Seq<A>) -> Seq<A> {
142 Seq::<A> {
143 _p: PhantomData,
144 bv: Bv::from_bitslice(&(self.bv | rhs.bv)),
145 }
146 }
147
148 pub fn push(&mut self, item: A) {
149 let byte: u8 = item.to_bits();
150 self.bv
151 .extend_from_bitslice(&byte.view_bits::<Order>()[..A::BITS as usize]);
152 }
153
154 pub fn clear(&mut self) {
155 self.bv.clear();
156 }
157
158 pub fn truncate(&mut self, len: usize) {
166 self.bv.truncate(len * A::BITS as usize);
167 }
168
169 pub fn prepend(&mut self, other: &SeqSlice<A>) {
177 let mut bv = Bv::with_capacity(self.bv.len() + other.bs.len());
178 bv.extend_from_bitslice(&other.bs);
179 bv.extend_from_bitslice(&self.bv);
180 self.bv = bv;
181 }
182
183 pub fn append(&mut self, other: &SeqSlice<A>) {
191 self.bv.extend_from_bitslice(&other.bs);
192 }
193
194 pub fn insert(&mut self, index: usize, other: &SeqSlice<A>) {
220 assert!(index <= self.len(), "Index out of bounds");
221
222 let i = index * A::BITS as usize;
223 let mut bv = Bv::with_capacity(self.bv.len() + other.bs.len());
224
225 bv.extend_from_bitslice(&self.bs[..i]);
226 bv.extend_from_bitslice(&other.bs);
227 bv.extend_from_bitslice(&self.bs[i..]);
228
229 self.bv = bv;
230 }
231
232 pub fn remove<R: RangeBounds<usize>>(&mut self, range: R) {
240 let (s, e) = self.bit_range(range);
241 self.bv.drain(s..e);
242 }
243
244 pub fn extend<I: IntoIterator<Item = A>>(&mut self, iter: I) {
245 iter.into_iter().for_each(|base| self.push(base));
246 }
247
248 pub fn from_raw(len: usize, bits: &[usize]) -> Option<Self> {
256 let mut bv: Bv = Bv::from_slice(bits);
257 let bit_len = len.checked_mul(A::BITS as usize)?;
258
259 if bit_len > bv.len() {
260 return None;
261 }
262 bv.truncate(bit_len);
263 Some(Seq {
264 _p: PhantomData,
265 bv,
266 })
267 }
268
269 pub fn into_raw(&self) -> &[usize] {
278 self.bv.as_raw_slice()
279 }
280}
281
282impl<A: Codec> ReverseMut for Seq<A> {
283 fn rev(&mut self) {
284 self.bv.reverse();
285 for chunk in self.bv.rchunks_exact_mut(A::BITS as usize) {
286 chunk.reverse();
287 }
288 }
289}
290
291impl<A: Codec + ComplementMut> ComplementMut for Seq<A> {
292 fn comp(&mut self) {
293 unsafe {
294 for base in self.bv.chunks_exact_mut(A::BITS as usize).remove_alias() {
295 let mut bc = A::unsafe_from_bits(base.load_le::<u8>());
296 bc.comp();
297 base.store(bc.to_bits() as usize);
298 }
299 }
300 }
301}
302
303impl<A: Codec + MaskableMut> MaskableMut for Seq<A> {
304 fn mask(&mut self) {
305 unsafe {
306 for base in self.bv.chunks_exact_mut(A::BITS as usize).remove_alias() {
307 let mut bc = A::unsafe_from_bits(base.load_le::<u8>());
308 bc.mask();
309 base.store(bc.to_bits() as usize);
310 }
311 }
312 }
313 fn unmask(&mut self) {
314 unsafe {
315 for base in self.bv.chunks_exact_mut(A::BITS as usize).remove_alias() {
316 let mut bc = A::unsafe_from_bits(base.load_le::<u8>());
317 bc.unmask();
318 base.store(bc.to_bits() as usize);
319 }
320 }
321 }
322}
323
324impl<A: Codec + MaskableMut> Maskable for Seq<A> {}
325
326impl<A: Codec + ComplementMut> ReverseComplementMut for Seq<A> where
327 Seq<A>: ComplementMut + ReverseMut
328{
329}
330
331impl<A: Codec> Reverse for Seq<A> {}
332
333impl<A: Codec + ComplementMut> Complement for Seq<A> {}
334
335impl<A: Codec + ComplementMut> ReverseComplement for Seq<A> where Seq<A>: ComplementMut + ReverseMut {}
336
337impl<A: Codec> PartialEq<SeqSlice<A>> for Seq<A> {
338 fn eq(&self, other: &SeqSlice<A>) -> bool {
339 self.as_ref() == other
340 }
341}
342
343impl<A: Codec> PartialEq<&SeqSlice<A>> for Seq<A> {
344 fn eq(&self, other: &&SeqSlice<A>) -> bool {
345 self.as_ref() == *other
346 }
347}
348
349impl<A: Codec> PartialEq<Seq<A>> for &Seq<A> {
350 fn eq(&self, other: &Seq<A>) -> bool {
351 **self == *other
352 }
353}
354
355impl<A: Codec> PartialEq<&Seq<A>> for Seq<A> {
356 fn eq(&self, other: &&Seq<A>) -> bool {
357 *self == **other
358 }
359}
360
361impl<A: Codec> Borrow<SeqSlice<A>> for Seq<A> {
385 fn borrow(&self) -> &SeqSlice<A> {
386 self.as_ref()
387 }
388}
389
390impl<A: Codec> Borrow<SeqSlice<A>> for &Seq<A> {
391 fn borrow(&self) -> &SeqSlice<A> {
392 self.as_ref()
393 }
394}
395
396impl<A: Codec> Deref for Seq<A> {
410 type Target = SeqSlice<A>;
411
412 fn deref(&self) -> &Self::Target {
413 let bs: *const Bs = ptr::from_ref::<Bs>(&self.bv);
414 unsafe { &*(bs as *const SeqSlice<A>) }
415 }
416}
417
418impl<A: Codec> AsRef<SeqSlice<A>> for Seq<A> {
432 fn as_ref(&self) -> &SeqSlice<A> {
433 self
434 }
435}
436
437impl<A: Codec> Clone for Seq<A> {
450 fn clone(&self) -> Self {
451 Self {
452 _p: PhantomData,
453 bv: self.bv.clone(),
454 }
455 }
456}
457
458impl<A: Codec> FromIterator<A> for Seq<A> {
459 fn from_iter<I: IntoIterator<Item = A>>(iter: I) -> Self {
460 let i = iter.into_iter();
461 let mut seq = Seq::with_capacity(i.size_hint().0);
462 seq.extend(i);
463 seq
464 }
465}
466
467impl<A: Codec> From<&Vec<A>> for Seq<A> {
468 fn from(vec: &Vec<A>) -> Self {
469 vec.iter().copied().collect()
472 }
473}
474
475impl<A: Codec, B: Codec> From<&SeqSlice<A>> for Seq<B>
476where
477 A: Into<B>,
478{
479 fn from(slice: &SeqSlice<A>) -> Self {
480 slice.iter().map(Into::into).collect()
481 }
482}
483
484impl<A: Codec, B: Codec, const N: usize, const W: usize> From<&SeqArray<A, N, W>> for Seq<B>
485where
486 A: Into<B>,
487{
488 fn from(slice: &SeqArray<A, N, W>) -> Self {
489 slice.iter().map(Into::into).collect()
490 }
491}
492
493impl<A: Codec, B: Codec, const N: usize, const W: usize> From<SeqArray<A, N, W>> for Seq<B>
494where
495 A: Into<B>,
496{
497 fn from(slice: SeqArray<A, N, W>) -> Self {
498 slice.iter().map(Into::into).collect()
499 }
500}
501
502impl<A: Codec> TryFrom<&str> for Seq<A> {
503 type Error = ParseBioError;
504
505 fn try_from(s: &str) -> Result<Self, Self::Error> {
506 Seq::<A>::try_from(s.as_bytes())
507 }
508}
509
510impl<A: Codec> TryFrom<String> for Seq<A> {
511 type Error = ParseBioError;
512
513 fn try_from(s: String) -> Result<Self, Self::Error> {
514 Seq::<A>::try_from(s.as_str())
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> FromStr for Seq<A> {
527 type Err = ParseBioError;
528
529 fn from_str(s: &str) -> Result<Self, Self::Err> {
530 Seq::<A>::try_from(s)
531 }
532}
533
534impl<A: Codec> TryFrom<&[u8]> for Seq<A> {
535 type Error = ParseBioError;
536
537 fn try_from(v: &[u8]) -> Result<Self, Self::Error> {
538 Self::try_from(v.to_vec())
539 }
540}
541
542impl<A: Codec> TryFrom<Vec<u8>> for Seq<A> {
543 type Error = ParseBioError;
544
545 fn try_from(v: Vec<u8>) -> Result<Self, Self::Error> {
546 v.into_iter()
550 .map(|byte| A::try_from_ascii(byte).ok_or(ParseBioError::UnrecognisedBase(byte)))
551 .collect()
552 }
553}
554
555impl<A: Codec> From<Seq<A>> for String {
556 fn from(seq: Seq<A>) -> Self {
557 String::from(seq.as_ref())
558 }
559}
560
561impl<A: Codec> From<&Seq<A>> for String {
562 fn from(seq: &Seq<A>) -> Self {
563 String::from(seq.as_ref())
564 }
565}
566
567impl<A: Codec> fmt::Display for Seq<A> {
568 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
569 fmt::Display::fmt(self.as_ref(), f)
570 }
571}
572
573impl<A: Codec> Extend<A> for Seq<A> {
574 fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T) {
575 self.extend(iter);
576 }
577}
578
579impl From<Vec<usize>> for Seq<text::Dna> {
580 fn from(vec: Vec<usize>) -> Self {
581 Seq {
582 _p: PhantomData,
583 bv: Bv::from_vec(vec),
584 }
585 }
586}
587
588impl<A: Codec> From<&Bs> for Seq<A> {
590 fn from(bs: &Bs) -> Self {
591 Seq {
592 _p: PhantomData,
593 bv: bs.into(),
594 }
595 }
596}
597
598impl<A: Codec> From<Bv> for Seq<A> {
600 fn from(bv: Bv) -> Self {
601 Seq {
602 _p: PhantomData,
603 bv,
604 }
605 }
606}
607
608#[cfg(test)]
609mod tests {
610 use crate::codec::text;
611 use crate::prelude::*;
612 use crate::{Bv, Order};
613 use bitvec::prelude::*;
614 use core::borrow::Borrow;
615 use core::hash::{Hash, Hasher};
616 use core::marker::PhantomData;
617 use std::collections::hash_map::DefaultHasher;
618
619 #[test]
620 fn test_revcomp() {
621 let s1: Seq<Dna> = dna!("ATGTGTGCGACTGA").into();
622 let mut s2: Seq<Dna> = dna!("TCAGTCGCACACAT").into();
623 let s3: &SeqSlice<Dna> = &s1;
624
625 assert_eq!(s3.to_revcomp(), s2.to_revcomp().to_revcomp());
626 assert_eq!(s3.to_revcomp(), &s2);
627
628 s2.revcomp();
629
630 assert_eq!(s3.to_revcomp(), s2.to_revcomp());
631 assert_ne!(s3, s2.to_revcomp());
632 }
633
634 #[test]
635 fn test_revcomp_mismatched_sizes() {
636 let s1 = dna!("AAAA");
637 let mut s2: Seq<Dna> = dna!("TTTTT").into();
638 s2.revcomp();
639 assert_ne!(s1, s2);
640 }
641
642 #[test]
643 fn test_revcomp_idempotence() {
644 let mut s = dna!("AAACGCTACGTACGCGCCTTCGGGGCATCAGCACCAC").to_owned();
645 let sc = dna!("AAACGCTACGTACGCGCCTTCGGGGCATCAGCACCAC");
646 s.revcomp();
647 assert_eq!(s.to_revcomp(), sc);
648 s.comp();
649 s.rev();
650 s.rev();
651 s.comp();
652 assert_eq!(s.to_revcomp(), sc);
653 }
654 #[test]
655 fn slice_index_comparisions() {
656 let s1 = dna!("ATGTGTGCGACTGATGATCAAACGTAGCTACG");
657 let s2 = dna!("ACGTGTGTGCTAGCTAATCGATCAAAAAG");
658
659 assert_eq!(&s1[0], &s2[0]);
660 assert_ne!(&s1[1], &s2[1]);
661 assert_eq!(&s1[2..4], &s2[2..4]);
662 assert_eq!(&s1[15..21], &s2[19..25]);
663 assert_ne!(&s1[2..20], &s2[2..20]);
664 }
665
666 #[test]
667 #[allow(clippy::redundant_slicing)]
668 fn slice_index_owned() {
669 let seq = dna!("GCTCGATCACT");
670
671 assert_eq!(&seq[..], dna!("GCTCGATCACT"));
672 assert_eq!(&seq[..=4], dna!("GCTCG"));
673 assert_eq!(&seq[1..=4], dna!("CTCG"));
674 assert_eq!(&seq[1..4], dna!("CTC"));
675 assert_eq!(&seq[..4], dna!("GCTC"));
676 assert_eq!(&seq[1..], dna!("CTCGATCACT"));
677 }
678
679 #[test]
680 #[allow(clippy::redundant_slicing)]
681 fn slice_indexing() {
682 let seq = dna!("TGCATCGAT");
683
684 assert_ne!(&seq[..], &dna!("AGCATCGAA")[..]);
685 assert_ne!(&seq[3..=6], &dna!("ATC")[..]);
686 assert_ne!(&seq[..=6], &dna!("TGCATC")[..]);
687 assert_ne!(&seq[4..5], &dna!("TC")[..]);
688 assert_ne!(&seq[..6], &dna!("TGCAT")[..]);
689 assert_ne!(&seq[5..], &dna!("TCGAT")[..]);
690
691 assert_eq!(&seq[..], &dna!("TGCATCGAT")[..]);
692 assert_eq!(&seq[3..=6], &dna!("ATCG")[..]);
693 assert_eq!(&seq[..=6], &dna!("TGCATCG")[..]);
694 assert_eq!(&seq[4..5], &dna!("T")[..]);
695 assert_eq!(&seq[..6], &dna!("TGCATC")[..]);
696 assert_eq!(&seq[5..], &dna!("CGAT")[..]);
697 }
698
699 #[test]
700 #[allow(clippy::redundant_slicing)]
701 fn slice_index_ranges() {
702 let s1: &'static SeqSlice<Dna> = dna!("ACGACTGATCGA");
703 let s2: &'static SeqSlice<Dna> = dna!("TCGAACGACTGA");
704
705 assert_eq!(&s1[..8], &s2[4..]);
706 assert_eq!(&s1[8..], &s2[..4]);
707 assert_ne!(&s1[8..], &s2[8..]);
708 assert_ne!(&s1[..], &s2[..4]);
709
710 assert_eq!(&s1[..=7], &s2[4..]);
711 assert_eq!(&s1[8..], &s2[..=3]);
712 assert_ne!(&s1[8..11], &s2[8..=11]);
713 assert_ne!(&s1[..], &s2[..=4]);
714 }
715
716 #[test]
717 fn slice_nth() {
718 let s = dna!("ATGTGTGCGACTGATGATCAAACGTAGCTACG");
719
720 assert_eq!(s.nth(0), Dna::A);
721 assert_ne!(s.nth(0), Dna::G);
722
723 assert_eq!(s.nth(1), Dna::T);
724 assert_ne!(s.nth(1), Dna::C);
725
726 assert_eq!(s.nth(s.len() - 1), Dna::G);
727 assert_ne!(s.nth(s.len() - 1), Dna::C);
728 }
729
730 #[test]
731 #[allow(clippy::redundant_slicing)]
732 fn slice_rangeto_and_full() {
733 let s1 = dna!("ATCGACTAGCATGCTACG");
734 let s2 = dna!("ATCGACTAG");
735
736 assert_eq!(&s1[..s2.len()], &s2[..]);
737 assert_ne!(&s2[..s2.len()], &s1[..]);
738 }
739
740 #[test]
741 fn from_slice() {
742 let s1 = dna!("ATGTGTGCGACTGATGATCAAACGTAGCTACG");
743 let s: &SeqSlice<Dna> = &s1[15..21];
744 assert_eq!(format!("{s}"), "GATCAA");
745 }
746
747 #[test]
748 fn string_to_seq() {
749 let seq_str = "ACTGACTG";
750 let seq: Result<Seq<Dna>, _> = seq_str.try_into();
751 assert!(seq.is_ok());
752 assert_eq!(seq.unwrap().to_string(), seq_str);
753 }
754
755 #[test]
756 fn invalid_string_to_seq() {
757 let invalid_seq_str = "ACUGACTG";
758 let seq: Result<Seq<Dna>, _> = invalid_seq_str.try_into();
759 assert!(seq.is_err());
760 }
761
762 #[test]
763 fn seq_to_string() {
764 let seq_str = "ACTGACTG";
765 let seq: Seq<Dna> = seq_str.try_into().unwrap();
766 let result_str: String = seq.into();
767 assert_eq!(result_str, seq_str);
768 }
769
770 #[test]
771 fn seqslice_to_string() {
772 let seq_str = "ACTGACTG";
773 let seq: Seq<Dna> = seq_str.try_into().unwrap();
774 let slice = &seq[1..5];
775 let result_str: String = slice.into();
776 assert_eq!(result_str, "CTGA");
777 }
778
779 #[test]
780 #[should_panic(expected = "range 2..18 out of bounds: 16")]
781 fn invalid_seqslice_to_string() {
782 let seq_str = "ACTGACTG";
783 let seq: Seq<Dna> = seq_str.try_into().unwrap();
784 let _ = &seq[1..9];
785 }
786
787 #[test]
788 fn test_push() {
789 let mut seq = Seq::<Dna>::new();
790 seq.push(Dna::A);
791 seq.push(Dna::C);
792 seq.push(Dna::G);
793 seq.push(Dna::T);
794
795 assert_eq!(seq.len(), 4);
796 assert_eq!(String::from(seq), "ACGT");
797 }
798
799 #[test]
800 fn test_extend_amino() {
801 let mut seq = Seq::<Amino>::new();
802 seq.push(Amino::S);
803 seq.push(Amino::L);
804
805 seq.extend(vec![Amino::Y, Amino::M]);
806
807 assert_eq!(seq.len(), 4);
808 assert_eq!(String::from(seq), "SLYM");
809 }
810 #[test]
811 fn test_extend() {
812 let mut seq = Seq::<Dna>::new();
813 seq.push(Dna::A);
814 seq.push(Dna::C);
815
816 seq.extend(vec![Dna::G, Dna::T]);
817
818 assert_eq!(seq.len(), 4);
819 assert_eq!(String::from(seq), "ACGT");
820 }
821
822 #[test]
823 fn test_eqs() {
824 let seq: Seq<Dna> = "ACTAGCATCGA".try_into().unwrap();
825 let seq2: Seq<Dna> = "ACTAGCATCGA".try_into().unwrap();
826 let slice: &SeqSlice<Dna> = &seq;
827 let slice2: &SeqSlice<Dna> = &seq2[..];
828 assert_eq!(seq, slice);
829 assert_eq!(seq2, slice);
830 assert_eq!(seq2, slice2);
831 assert_eq!(slice, slice2);
832 assert_eq!(seq, seq2);
833 }
834
835 #[test]
836 fn test_str_eqs() {
837 let string: String = "ACTAGCATCGA".into();
838 let slice: &str = "GCTGCATCGATC";
839
840 let seq1: Seq<Dna> = Seq::<Dna>::try_from(slice).unwrap();
841 let seq2: Seq<Dna> = Seq::<Dna>::try_from(string.clone()).unwrap();
842
843 assert_eq!(seq2.to_string(), string);
844 assert_eq!(seq1.to_string(), slice);
845
846 assert_ne!(seq2.to_string(), slice);
847 assert_ne!(seq1.to_string(), string);
848 }
849
850 #[test]
851 fn test_from_iter() {
852 let iter = vec![Dna::A, Dna::C, Dna::G, Dna::T].into_iter();
853 let seq: Seq<Dna> = Seq::from_iter(iter);
854
855 assert_eq!(seq.len(), 4);
856 assert_eq!(String::from(seq), "ACGT");
857 }
858
859 #[test]
860 fn test_bit_order() {
861 let raw: usize = 0b10_11_01_11_10_01_00_01;
862 let mut bv: Bv = BitVec::default();
863 bv.extend(&raw.view_bits::<Order>()[..(Dna::BITS as usize * 8)]);
864 let s = Seq::<Dna> {
865 bv,
866 _p: PhantomData,
867 };
868 assert_eq!(dna!("CACGTCTG").to_string(), "CACGTCTG");
869 assert_eq!(String::from(s), "CACGTCTG");
870 }
872
873 #[test]
874 fn test_borrow() {
875 let seq: Seq<Dna> = dna!("ACGACCCCCATAGATGGGCTG").into();
876 let slice: &SeqSlice<Dna> = seq.borrow();
877 assert_eq!(slice, &seq[..]);
878 assert_ne!(slice, &seq[1..]);
879 }
880
881 #[test]
882 #[allow(clippy::explicit_auto_deref)]
883 fn test_deref() {
884 let seq: Seq<Dna> = dna!("AGAATGATCG").into();
885 let slice: &SeqSlice<Dna> = &*seq;
886
887 assert_eq!(slice, &seq[..]);
888 assert_ne!(slice, &seq[1..]);
889 }
890
891 #[test]
892 fn test_asref() {
893 let seq: Seq<Dna> = dna!("AGAATGATCAAAATATATATAAAG").into();
894 let slice: &SeqSlice<Dna> = seq.as_ref();
895 assert_ne!(slice, &seq[2..5]);
896 assert_eq!(slice, &seq[..]);
897 }
898
899 #[test]
900 fn test_to_owned() {
901 let seq: Seq<Dna> = dna!("AGAATGAATCG").into();
902 let slice: &SeqSlice<Dna> = &seq;
903 let owned: Seq<Dna> = slice[2..5].to_owned();
904 assert_eq!(&owned, &seq[2..5]);
905 assert_eq!(owned, seq[2..5].to_owned());
906 assert_ne!(&owned, &seq[..]);
907 }
908
909 #[test]
910 fn test_clone() {
911 let seq: Seq<Dna> = dna!("AGAATGATGGGGGGGGGGGCG").into();
912 let cloned = seq.clone();
913 assert_eq!(seq, cloned);
914 }
915 #[test]
916 fn test_trim() {
917 let seq = b"AGAATGATGGGGGGGGGGGCG";
918 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
919 assert_eq!(s, dna!("AGAATGATGGGGGGGGGGGCG"));
920
921 let seq = b"NNNNAGAATGATGGGGGGGGGGGCGNNNNNNNNNNN";
922 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
923 assert_eq!(s, dna!("AGAATGATGGGGGGGGGGGCG"));
924
925 let seq = b"NNNNAGAATGATGGGGNGGGGGGGCGNNNNNNNNNNN";
926 let s: Result<Seq<Dna>, ParseBioError> = Seq::trim_u8(seq);
927 assert_eq!(s, Err(ParseBioError::UnrecognisedBase(b'N')));
928
929 let seq = b"AGAATGATGGGGGGGGGGGCG";
930 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
931 assert_eq!(s, dna!("AGAATGATGGGGGGGGGGGCG"));
932
933 let seq = b"NNNNAGAATGATGGGGGGGGGGGCGNNNNNNNNNNN";
934 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
935 assert_eq!(s, dna!("AGAATGATGGGGGGGGGGGCG"));
936
937 let seq = b"NNNNAGAATGATGGGGNGGGGGGGCGNNNNNNNNNNN";
938 let s: Result<Seq<Dna>, ParseBioError> = Seq::trim_u8(seq);
939 assert_eq!(s, Err(ParseBioError::UnrecognisedBase(b'N')));
940
941 let seq = b"";
942 let s: Result<Seq<Dna>, ParseBioError> = Seq::trim_u8(seq);
943 assert!(s.is_ok());
944 assert_eq!(s.unwrap(), dna!(""));
945
946 let seq = b"XXXX";
947 let s: Result<Seq<Dna>, ParseBioError> = Seq::trim_u8(seq);
948 assert!(s.is_ok());
949 assert_eq!(s.unwrap(), dna!(""));
950
951 let seq = b"XXACGT";
952 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
953 assert_eq!(s, dna!("ACGT"));
954
955 let seq = b"ACGTXX";
956 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
957 assert_eq!(s, dna!("ACGT"));
958
959 let seq = b"ACGTACGTACGTACGTACGTACGT";
960 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
961 assert_eq!(s, dna!("ACGTACGTACGTACGTACGTACGT"));
962
963 let seq = b"XXACGTXXACGTXX";
964 let s: Result<Seq<Dna>, ParseBioError> = Seq::trim_u8(seq);
965 assert_eq!(s, Err(ParseBioError::UnrecognisedBase(b'X')));
966
967 let seq = b"A";
968 let s: Seq<Dna> = Seq::trim_u8(seq).unwrap();
969 assert_eq!(s, dna!("A"));
970
971 let seq = b"X";
972 let s: Result<Seq<Dna>, ParseBioError> = Seq::trim_u8(seq);
973 assert!(s.is_ok());
974 assert_eq!(s.unwrap(), dna!(""));
975
976 }
990
991 #[test]
992 fn test_seq_eq_and_hash() {
993 let seq1: Seq<Dna> = "ACGT".try_into().unwrap();
994 let seq2: Seq<Dna> = "ACGT".try_into().unwrap();
995
996 assert_eq!(seq1, seq2);
998
999 let mut hasher1 = DefaultHasher::new();
1001 seq1.hash(&mut hasher1);
1002 let hash1 = hasher1.finish();
1003
1004 let mut hasher2 = DefaultHasher::new();
1005 seq2.hash(&mut hasher2);
1006 let hash2 = hasher2.finish();
1007
1008 assert_eq!(hash1, hash2);
1009
1010 assert_eq!(record(&seq1), [4, 0, 0, 0, 0, 0, 0, 0, 0xe4]);
1011 }
1012
1013 #[test]
1014 #[allow(clippy::similar_names)]
1015 fn test_seq_slice_eq() {
1016 let seq1: Seq<Dna> = "ACGTAAAAAAAAAAAAACGTAAAACCCCGGGGTTTTA".try_into().unwrap();
1017 let seq2: Seq<Dna> = "ACGTAAAAAAAAAAAAACGTAAAACCCCGGGGTTTTAA".try_into().unwrap();
1018
1019 let slice1a: &SeqSlice<Dna> = &seq1[..];
1020 let slice1b: &SeqSlice<Dna> = &seq1[..];
1021 let slice2a: &SeqSlice<Dna> = &seq2[..seq2.len() - 1];
1022 let slice2b: &SeqSlice<Dna> = &seq2[..seq2.len() - 1];
1023
1024 let seq3: Seq<Dna> = slice2b.into();
1025
1026 assert_eq!(slice1a, slice2b);
1027 assert_eq!(&slice2a, &slice2b);
1028 assert_eq!(seq1, slice2a);
1029 assert_eq!(slice1b, seq3);
1030 assert_eq!(slice1a, slice1b);
1031 assert_eq!(seq1, seq3);
1032
1033 assert_ne!(seq1, seq2);
1034 assert_ne!(seq2, seq3);
1035 assert_ne!(seq2, slice2a);
1036 assert_ne!(seq2, slice1b);
1037
1038 assert_eq!(&slice1a, &slice1b);
1039
1040 assert_eq!(seq1, &seq1);
1041
1042 assert_eq!(seq1, &seq3);
1043 assert_eq!(&seq1, seq3);
1044 assert_eq!(&seq1, &seq3);
1045
1046 assert_eq!(slice1a, seq3);
1047 assert_eq!(seq1, slice2a);
1050 assert_eq!(&seq1, slice2a);
1051 assert_eq!(&seq1, slice2a);
1054 }
1055 #[test]
1056 fn test_seq_slice_hash() {
1057 let seq1: Seq<Dna> = "ACGTAAAAAAAAAAAAACGTAAAACCCCGGGGAAAAA".try_into().unwrap();
1058 let seq2: Seq<Dna> = "ACGTAAAAAAAAAAAAACGTAAAACCCCGGGGAAAAA".try_into().unwrap();
1059
1060 let seq3: Seq<Dna> = "ACGTAAAAAAAAAAAAACGTAAAACCCCGGGG".try_into().unwrap();
1061
1062 let slice1 = &seq1[..];
1063 let slice2 = &seq2[..];
1064
1065 let slice3 = &seq3[..];
1066
1067 let slice1_32 = &seq1[..32];
1068
1069 let mut hasher1 = DefaultHasher::new();
1070 seq1.hash(&mut hasher1);
1071 let full1 = hasher1.finish();
1072
1073 let mut hasher1a = DefaultHasher::new();
1074 seq1.hash(&mut hasher1a);
1075 let full1_alt = hasher1a.finish();
1076
1077 let mut hasher2 = DefaultHasher::new();
1078 seq2.hash(&mut hasher2);
1079 let full2 = hasher2.finish();
1080
1081 let mut hasher3 = DefaultHasher::new();
1082 slice1.hash(&mut hasher3);
1083 let full1_slice = hasher3.finish();
1084
1085 let mut hasher4 = DefaultHasher::new();
1086 slice2.hash(&mut hasher4);
1087 let full2_slice = hasher4.finish();
1088
1089 let mut hasher5 = DefaultHasher::new();
1090 slice3.hash(&mut hasher5);
1091 let short1_slice = hasher5.finish();
1092
1093 let mut hasher6 = DefaultHasher::new();
1094 slice1_32.hash(&mut hasher6);
1095 let seq1_short = hasher6.finish();
1096
1097 assert_eq!(full1, full1_alt);
1098 assert_eq!(full1, full2);
1099 assert_ne!(full2_slice, short1_slice);
1100 assert_eq!(full2, full1_slice);
1101 assert_eq!(short1_slice, seq1_short);
1102 assert_ne!(seq1_short, full1_slice);
1103
1104 assert_ne!(full1, short1_slice);
1105 }
1106
1107 #[test]
1108 fn test_fromstr() {
1109 let seq: Result<Seq<Dna>, ParseBioError> =
1110 "ACGATGAGTAGTCGCCATCGTATCTTTGACTGCCGATGCTA".parse();
1111 assert!(seq.is_ok());
1112
1113 let seq: Result<Seq<Dna>, ParseBioError> =
1114 "ACGATGAGTAGBCGCCATCGTATCTTTGACTGCCGATGCTA".parse();
1115 assert_eq!(seq, Err(ParseBioError::UnrecognisedBase(b'B')));
1116 }
1117
1118 #[test]
1119 fn test_lens() {
1120 assert_eq!(iupac!("AWANWATNA---SKAGTCAA").len(), 20);
1121 }
1122
1123 #[test]
1124 fn test_unique_bitarray_ident() {
1125 let s1 = dna!(
1126 "ATCGACTACGATCGCTACGATCGATCGATCGATCGAATCTCCCGCGCGATCATCGATCATCGCTACGTACGTCGAAAAATATAATGGG"
1127 );
1128 let s2 = dna!(
1129 "ATCGACTACGATCGCTACGATCGATCGATCGATCGAATCTCCCGCGCGATCATCGATCATCGCTACGTACGTCGAAAAATATAATGGG"
1130 );
1131
1132 let s3 = dna!(
1134 "CTCGACTACGATCGCTACGATCGATCGATCGATCGAATCTCCCGCGCGATCATCGATCATCGCTACGTACGTCGAAAAATATAATGGG"
1135 );
1136
1137 let s4 = dna!(
1139 "ATCGACTACGATCGCTACGATCGATCGATCGATCGAATCTCCCGCGCGATCATCGATCATCGCTACGTACGTCGAAAAATATAATGGGA"
1140 );
1141
1142 let s5 = dna!(
1144 "ATCGACTACGATCGCTACGATCGATCGATCGATCGAATCTCCCGCGCGATCATCGATCATCGCTACGTACGTCGAAAAATATAATGGC"
1145 );
1146
1147 assert_eq!(s1, s2);
1148 assert_ne!(s1, s3);
1149
1150 assert_ne!(s1.len(), s4.len());
1152 assert_ne!(s4.len(), s1.len());
1153
1154 assert_ne!(s5, s1);
1155 }
1156
1157 #[test]
1158 fn test_static() {
1159 use crate::seq::SeqArray;
1160
1161 static B: SeqArray<Dna, 5, 1> = SeqArray {
1162 _p: PhantomData,
1163 ba: bitarr![const usize, Lsb0; 1,1,0,1,0,0,1,0,1,1],
1164 };
1165
1166 let s: &'static SeqSlice<Dna> = &B;
1167
1168 let x: &'static str = "TGACT";
1169
1170 assert_eq!(s.to_string(), x);
1171 }
1172
1173 #[test]
1174 fn test_to_from_raw() {
1175 let s = "TCAGCTAGCTACGACTGATCGATCGACTGATGCCGCGCGCGGCGCCGCGCGCGCGCGCCGCGCGCCCCGCGCGCGGCGCGCGCCGCGCGCGCGCGCGGCGCGCGCGCGCGCGCGCGCGCGCGCGCGCGCGC";
1176
1177 let seq: Seq<Dna> = s.try_into().unwrap();
1178 let raw = seq.into_raw();
1179 let new = Seq::<Dna>::from_raw(s.len(), raw);
1180 assert_eq!(new.unwrap(), seq);
1181
1182 let bad = Seq::<Dna>::from_raw(s.len() + 1, raw);
1183 assert_ne!(bad.unwrap(), seq);
1184
1185 let bad = Seq::<Dna>::from_raw(342, raw);
1186 assert_eq!(bad, None);
1187 }
1188 #[test]
1189 fn test_seq_and_seq_slice_eq_and_hash() {
1190 let seq: Seq<text::Dna> = Seq::try_from("ACGT".to_string()).unwrap();
1191 let slice = &seq[..];
1192
1193 assert_eq!(seq, slice);
1195 assert_eq!(&seq, slice);
1196 assert_eq!(slice, &seq);
1197
1198 let mut hasher1 = std::collections::hash_map::DefaultHasher::new();
1200 seq.hash(&mut hasher1);
1201 let hash1 = hasher1.finish();
1202
1203 let mut hasher2 = std::collections::hash_map::DefaultHasher::new();
1204 slice.hash(&mut hasher2);
1205 let hash2 = hasher2.finish();
1206
1207 assert_eq!(hash1, hash2);
1208 }
1209
1210 #[derive(Default)]
1211 struct RecordingHasher(Vec<u8>);
1212
1213 impl Hasher for RecordingHasher {
1214 fn finish(&self) -> u64 {
1215 0
1216 }
1217 fn write(&mut self, bytes: &[u8]) {
1218 self.0.extend_from_slice(bytes);
1219 }
1220 }
1221
1222 fn record<T: Hash>(value: &T) -> Vec<u8> {
1223 let mut h = RecordingHasher::default();
1224 value.hash(&mut h);
1225 h.0
1226 }
1227
1228 #[test]
1229 fn test_hash_byte_stream_invariants() {
1230 fn check<A: Codec>(s: &str) {
1235 let seq: Seq<A> = s.try_into().unwrap_or_else(|_| panic!("parse {s:?}"));
1236 let bytes = record(&seq);
1237 assert_eq!(record::<&SeqSlice<A>>(&&seq[..]), bytes);
1238
1239 let n = seq.len();
1241 let body = (n * A::BITS as usize).div_ceil(8);
1242 assert_eq!(bytes.len(), 8 + body);
1243 assert_eq!(&bytes[..8], &(n as u64).to_le_bytes());
1244 }
1245 check::<Dna>("A");
1246 check::<Dna>("ACGT");
1247 check::<Dna>("ACGTA");
1248 check::<Dna>(&"ACGT".repeat(80)); check::<Iupac>("AC");
1250 check::<Iupac>("ACG");
1251 check::<Iupac>("NRYKBDHV");
1252 check::<Amino>("MWLLP"); check::<text::Dna>("ACGT"); }
1255
1256 #[test]
1257 fn test_kmer_hash_independent_of_storage_width() {
1258 let seq: Seq<Dna> = "ACGTACGTAC".try_into().unwrap();
1259 let slice: &SeqSlice<Dna> = &seq[..];
1260 let bytes = record(&slice);
1261 let km_usize: Kmer<Dna, 10, usize> = slice.try_into().unwrap();
1262 let km_u64: Kmer<Dna, 10, u64> = slice.try_into().unwrap();
1263 let km_u128: Kmer<Dna, 10, u128> = slice.try_into().unwrap();
1264 assert_eq!(record(&km_usize), bytes);
1265 assert_eq!(record(&km_u64), bytes);
1266 assert_eq!(record(&km_u128), bytes);
1267 }
1268
1269 #[test]
1270 fn test_prepend() {
1271 let mut seq1 =
1272 Seq::<Dna>::from_str("GCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAAT").unwrap();
1273 seq1.prepend(dna!("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
1274 assert_eq!(
1275 seq1.to_string(),
1276 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAAT"
1277 );
1278
1279 let mut seq2 =
1280 Seq::<Dna>::from_str("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").unwrap();
1281 seq2.prepend(dna!("GCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAAT"));
1282 assert_eq!(
1283 seq2.to_string(),
1284 "GCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
1285 );
1286
1287 assert_ne!(seq1, seq2);
1288 }
1289
1290 #[test]
1291 fn test_append() {
1292 let mut seq1 =
1293 Seq::<Dna>::from_str("GCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAAT").unwrap();
1294 seq1.append(dna!("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"));
1295 assert_eq!(
1296 seq1.to_string(),
1297 "GCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAATAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA"
1298 );
1299
1300 let mut seq2 =
1301 Seq::<Dna>::from_str("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA").unwrap();
1302 seq2.append(dna!("GCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAAT"));
1303 assert_eq!(
1304 seq2.to_string(),
1305 "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGCTCGATCGATCGATCGACTGACTGACGCGCGCATCCGATAAAAAAAAT"
1306 );
1307
1308 assert_ne!(seq1, seq2);
1309 }
1310
1311 #[test]
1312 fn test_remove() {
1313 let mut seq: Seq<Dna> = dna!("TCAGCATCGATCAATCG").into();
1314 seq.remove(4..6);
1315 assert_eq!(&seq, dna!("TCAGTCGATCAATCG"));
1316 seq.remove(..4);
1317 assert_eq!(&seq, dna!("TCGATCAATCG"));
1318 seq.remove(6..);
1319 assert_eq!(&seq, dna!("TCGATC"));
1320 }
1321
1322 #[test]
1323 fn test_insert() {
1324 let mut seq: Seq<Dna> = dna!("TCAGCATCGATCAATCG").into();
1325 let insertion = dna!("CCCCC");
1326
1327 seq.insert(4, insertion);
1328 assert_eq!(&seq, dna!("TCAGCCCCCCATCGATCAATCG"));
1329
1330 seq.insert(seq.len(), dna!("AAAAA"));
1331 assert_eq!(&seq, dna!("TCAGCCCCCCATCGATCAATCGAAAAA"));
1332 }
1333
1334 #[test]
1335 fn test_truncate() {
1336 let mut seq: Seq<Dna> = dna!("TCAGCATCGATCAATCG").into();
1337
1338 seq.truncate(seq.len());
1339 assert_eq!(&seq, dna!("TCAGCATCGATCAATCG"));
1340
1341 seq.truncate(10);
1342 assert_eq!(&seq, dna!("TCAGCATCGA"));
1343
1344 seq.truncate(0);
1345 assert_eq!(&seq, dna!(""));
1346 }
1347
1348 }