1#![allow(clippy::cast_possible_truncation)]
32
33use crate::Bs;
34use crate::codec::{self, Codec};
35use crate::prelude::ParseBioError;
36use crate::seq::{Seq, SeqArray, SeqSlice};
37use crate::{
38 Complement, ComplementMut, Reverse, ReverseComplement, ReverseComplementMut, ReverseMut,
39};
40use bitvec::field::BitField;
41use bitvec::view::BitView;
42use core::fmt;
43use core::hash::{Hash, Hasher};
44use core::marker::PhantomData;
45use core::ops::Deref;
46use core::ptr;
47use core::str::FromStr;
48
49#[cfg(target_pointer_width = "64")]
56pub(crate) mod integral64;
57
58#[cfg(target_pointer_width = "32")]
59pub(crate) mod integral32;
60
61#[cfg(feature = "serde")]
62use serde_derive::{Deserialize, Serialize};
63
64const fn make_2bit_table() -> [u8; 256] {
65 let mut table = [0u8; 256];
66 let mut i: usize = 0;
67 while i < 256 {
68 let b0: u8 = (i as u8 & 0b11_00_00_00) >> 6;
69 let b1: u8 = (i as u8 & 0b00_11_00_00) >> 2;
70 let b2: u8 = (i as u8 & 0b00_00_11_00) << 2;
71 let b3: u8 = (i as u8 & 0b00_00_00_11) << 6;
72
73 table[i] = b3 | b2 | b1 | b0;
74 i += 1;
75 }
76 table
77}
78
79const REV_2BIT: [u8; 256] = make_2bit_table();
80
81pub(crate) mod sealed {
82 use crate::Bs;
83
84 pub trait KmerStorage: Copy + Clone + PartialEq + std::fmt::Debug {
85 const BITS: usize;
86 type BaN: AsRef<Bs> + AsMut<Bs>;
87
88 fn to_bitarray(self) -> Self::BaN;
89 fn from_bitslice(bs: &Bs) -> Self;
90
91 fn shiftr(&mut self, n: u32);
95
96 fn shiftl(&mut self, n: u32);
97
98 fn mask(&mut self, bits: usize);
99
100 fn complement(&mut self, mask: usize);
101 fn rev_blocks_2(&mut self);
102 }
103}
104
105pub trait KmerStorage: sealed::KmerStorage {}
106
107impl KmerStorage for usize {}
108
109impl KmerStorage for u64 {}
110
111impl KmerStorage for u128 {}
112
113#[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Copy, Clone)]
128#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]
129#[repr(transparent)]
130pub struct Kmer<C: Codec, const K: usize, S: KmerStorage = usize> {
131 pub _p: PhantomData<C>,
132 pub bs: S,
133}
134
135impl<A: Codec, const K: usize, S: KmerStorage> Kmer<A, K, S> {
136 const _ASSERT_K: () = assert!(
138 K * A::BITS as usize <= S::BITS,
139 "`KmerStorage` not large enough for `Kmer`",
140 );
141
142 const _ASSERT_K_NONZERO: () = assert!(K > 0, "`K` must be greater than 0");
143
144 const fn assert_k() {
145 let () = Self::_ASSERT_K;
146 let () = Self::_ASSERT_K_NONZERO;
147 }
148
149 const BITS: usize = K * A::BITS as usize;
150
151 pub fn len(&self) -> usize {
152 K
153 }
154
155 pub fn is_empty(&self) -> bool {
156 false
159 }
160
161 pub fn rotated_left(&self, n: u32) -> Self {
162 let n: usize = (n as usize % K) * A::BITS as usize;
163 let mut ba = self.bs.to_bitarray();
164 let bs: &mut Bs = ba.as_mut();
165 bs[..Self::BITS].rotate_left(n);
166
167 Kmer {
168 _p: PhantomData,
169 bs: S::from_bitslice(&bs[..Self::BITS]),
170 }
171 }
172
173 pub fn rotated_right(&self, n: u32) -> Self {
174 let n: usize = (n as usize % K) * A::BITS as usize;
175 let mut ba = self.bs.to_bitarray();
176 let bs: &mut Bs = ba.as_mut();
177 bs[..Self::BITS].rotate_right(n);
178
179 Kmer {
180 _p: PhantomData,
181 bs: S::from_bitslice(&bs[..Self::BITS]),
182 }
183 }
184
185 pub fn pushr(self, base: A) -> Self {
195 let mut ba = self.rotated_left(1).bs.to_bitarray();
196 let bs: &mut Bs = ba.as_mut();
197
198 let start = Self::BITS - A::BITS as usize;
199 let end = start + A::BITS as usize;
200
201 bs[start..end].store(base.to_bits());
202
203 Kmer {
204 _p: PhantomData,
205 bs: S::from_bitslice(bs),
206 }
207 }
208
209 pub fn pushl(self, base: A) -> Self {
211 let mut ba = self.rotated_right(1).bs.to_bitarray();
212 let bs: &mut Bs = ba.as_mut();
213
214 bs[..A::BITS as usize].store(base.to_bits());
215
216 Kmer {
217 _p: PhantomData,
218 bs: S::from_bitslice(bs),
219 }
220 }
221
222 pub fn unsafe_from_seqslice(seq: &SeqSlice<A>) -> Self {
224 Self::assert_k();
225 debug_assert!(K == seq.len(), "K != seq.len()");
226 Kmer {
227 _p: PhantomData,
228 bs: S::from_bitslice(&seq.bs),
229 }
230 }
231
232 fn complement(&mut self) {
233 self.bs.complement(K * A::BITS as usize);
234 }
235
236 fn rev_blocks_2(&mut self) {
237 self.bs.rev_blocks_2();
239 self.bs.shiftr((S::BITS - (A::BITS as usize * K)) as u32);
240 }
241}
242
243impl<A: Codec, const K: usize> From<usize> for Kmer<A, K, usize> {
244 fn from(i: usize) -> Kmer<A, K, usize> {
245 Self::assert_k();
246 Kmer {
247 _p: PhantomData,
248 bs: i,
249 }
250 }
251}
252
253impl<A: Codec, const K: usize> From<u64> for Kmer<A, K, u64> {
254 fn from(i: u64) -> Kmer<A, K, u64> {
255 Self::assert_k();
256 Kmer {
257 _p: PhantomData,
258 bs: i,
259 }
260 }
261}
262
263impl<A: Codec, const K: usize> From<usize> for Kmer<A, K, u64> {
264 fn from(i: usize) -> Kmer<A, K, u64> {
265 Self::assert_k();
266 Kmer {
267 _p: PhantomData,
268 bs: i as u64,
269 }
270 }
271}
272
273impl<S: KmerStorage + Into<usize>, A: Codec, const K: usize> From<&Kmer<A, K, S>> for usize {
285 fn from(kmer: &Kmer<A, K, S>) -> usize {
286 kmer.bs.into()
287 }
288}
289
290impl<A: Codec, const K: usize> Deref for Kmer<A, K, usize> {
291 type Target = SeqSlice<A>;
292
293 fn deref(&self) -> &Self::Target {
294 let bs: &Bs = &self.bs.view_bits()[0..(K * A::BITS as usize)];
295 let bs: *const Bs = ptr::from_ref::<Bs>(bs);
296 unsafe { &*(bs as *const SeqSlice<A>) }
297 }
298}
299
300impl<A: Codec, const K: usize> AsRef<SeqSlice<A>> for Kmer<A, K, usize> {
301 fn as_ref(&self) -> &SeqSlice<A> {
302 self
303 }
304}
305
306impl<A: Codec, const K: usize, S: KmerStorage> fmt::Display for Kmer<A, K, S> {
307 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
308 let mut s = String::new();
309 let ba = self.bs.to_bitarray();
310 let bs: &Bs = &ba.as_ref()[0..(K * A::BITS as usize)];
311
312 bs.chunks(A::BITS as usize).for_each(|chunk| {
313 s.push(A::unsafe_from_bits(chunk.load_le::<u8>()).to_char());
314 });
315 write!(f, "{s}")
316 }
317}
318
319pub struct KmerIter<'a, A: Codec, const K: usize> {
321 pub slice: &'a SeqSlice<A>,
322 pub index: usize,
323 pub len: usize,
324 pub _p: PhantomData<A>,
325}
326
327impl<A: Codec, const K: usize, S: KmerStorage> Kmer<A, K, S> {
328 fn unsafe_from(seq: &SeqSlice<A>) -> Self {
329 Self::assert_k();
330 debug_assert!(K == seq.len(), "K != seq.len()");
331 Kmer {
332 _p: PhantomData,
333 bs: S::from_bitslice(&seq.bs),
334 }
335 }
336}
337
338impl<A: Codec, const K: usize> Iterator for KmerIter<'_, A, K> {
339 type Item = Kmer<A, K>;
340 fn next(&mut self) -> Option<Kmer<A, K>> {
341 let i = self.index;
342 if self.index + K > self.len {
343 return None;
344 }
345 self.index += 1;
346 Some(Kmer::<A, K>::unsafe_from(&self.slice[i..i + K]))
347 }
348}
349
350impl<A: Codec, const K: usize, S: KmerStorage> Hash for Kmer<A, K, S> {
365 fn hash<H: Hasher>(&self, state: &mut H) {
366 state.write(&(K as u64).to_le_bytes());
368 let ba = self.bs.to_bitarray();
369 let bs: &Bs = ba.as_ref();
370 let n_bits = K * A::BITS as usize;
373 crate::hash::hash_bits(&bs[..n_bits], state);
374 }
375}
376
377impl<A: Codec, const K: usize, S: KmerStorage> TryFrom<&SeqSlice<A>> for Kmer<A, K, S> {
378 type Error = ParseBioError;
379
380 fn try_from(seq: &SeqSlice<A>) -> Result<Self, Self::Error> {
381 if seq.len() == K {
382 Ok(Kmer::<A, K, S>::unsafe_from(&seq[0..K]))
383 } else {
384 Err(ParseBioError::MismatchedLength(K, seq.len()))
385 }
386 }
387}
388
389impl<A: Codec, const K: usize> TryFrom<Seq<A>> for Kmer<A, K> {
390 type Error = ParseBioError;
391
392 fn try_from(seq: Seq<A>) -> Result<Self, Self::Error> {
393 Self::try_from(seq.as_ref())
394 }
395}
396
397impl<A: Codec, const K: usize, S: KmerStorage> PartialEq<SeqArray<A, K, 1>> for Kmer<A, K, S> {
398 fn eq(&self, seq: &SeqArray<A, K, 1>) -> bool {
399 if seq.len() != K {
400 return false;
401 }
402 &Kmer::<A, K, S>::unsafe_from(seq.as_ref()) == self
403 }
404}
405
406impl<A: Codec, const K: usize, S: KmerStorage> PartialEq<&SeqArray<A, K, 1>> for Kmer<A, K, S> {
407 fn eq(&self, seq: &&SeqArray<A, K, 1>) -> bool {
408 if seq.len() != K {
409 return false;
410 }
411 &Kmer::<A, K, S>::unsafe_from(seq.as_ref()) == self
412 }
413}
414
415impl<A: Codec, const K: usize> PartialEq<Seq<A>> for Kmer<A, K> {
416 fn eq(&self, seq: &Seq<A>) -> bool {
417 if seq.len() != K {
418 return false;
419 }
420 &Kmer::<A, K>::unsafe_from(seq.as_ref()) == self
421 }
422}
423
424impl<A: Codec, const K: usize, S: KmerStorage> PartialEq<SeqSlice<A>> for Kmer<A, K, S> {
425 fn eq(&self, seq: &SeqSlice<A>) -> bool {
426 if seq.len() != K {
427 return false;
428 }
429 &Kmer::<A, K, S>::unsafe_from(seq) == self
430 }
431}
432
433impl<A: Codec, const K: usize, S: KmerStorage> PartialEq<&SeqSlice<A>> for Kmer<A, K, S> {
434 fn eq(&self, seq: &&SeqSlice<A>) -> bool {
435 if seq.len() != K {
436 return false;
437 }
438 &Kmer::<A, K, S>::unsafe_from(seq) == self
439 }
440}
441
442impl<A: Codec, const K: usize> PartialEq<&str> for Kmer<A, K> {
443 fn eq(&self, seq: &&str) -> bool {
444 &self.to_string() == seq
445 }
446}
447
448impl<A: Codec, const K: usize, S: KmerStorage> FromStr for Kmer<A, K, S> {
449 type Err = ParseBioError;
450
451 fn from_str(s: &str) -> Result<Self, Self::Err> {
452 if s.len() != K {
453 return Err(ParseBioError::MismatchedLength(K, s.len()));
454 }
455 let seq: Seq<A> = Seq::from_str(s)?;
456 Kmer::<A, K, S>::try_from(seq.as_ref())
457 }
458}
459
460impl<A: Codec, const K: usize> From<Kmer<A, K, usize>> for Seq<A> {
461 fn from(kmer: Kmer<A, K, usize>) -> Self {
462 let mut seq: Seq<A> = Seq::with_capacity(K);
463 seq.extend(kmer.iter());
464 seq
465 }
466}
467
468impl<const K: usize> ComplementMut for Kmer<codec::dna::Dna, K, usize> {
469 fn comp(&mut self) {
470 self.complement();
471 }
472}
473
474impl<const K: usize> Complement for Kmer<codec::dna::Dna, K, usize> {}
475
476impl<A: Codec, const K: usize> ReverseMut for Kmer<A, K, usize> {
477 fn rev(&mut self) {
478 self.rev_blocks_2();
479 }
480}
481
482impl<A: Codec, const K: usize> Reverse for Kmer<A, K, usize> {}
483
484impl<const K: usize> ReverseComplementMut for Kmer<codec::dna::Dna, K, usize> {}
485
486impl<const K: usize> ReverseComplement for Kmer<codec::dna::Dna, K, usize> {}
487
488#[macro_export]
496macro_rules! kmer {
497 ($seq:expr) => {
498 Kmer::<Dna, { $seq.len() }>::unsafe_from_seqslice(dna!($seq))
499 };
500 ($seq:expr, $storage:ty) => {
501 Kmer::<Dna, { $seq.len() }, $storage>::unsafe_from_seqslice(dna!($seq))
502 };
503}
504
505#[cfg(test)]
506mod tests {
507 use crate::prelude::*;
508 use crate::seq::SeqArray;
509
510 #[test]
511 #[allow(clippy::cast_sign_loss)]
512 fn kmer_to_usize() {
513 let s: &'static SeqSlice<Dna> = dna!("AACTT");
514 println!("{s}");
515
516 for (kmer, index) in s.kmers::<2>().zip([0b00_00, 0b01_00, 0b11_01, 0b11_11]) {
517 println!("{kmer}");
518 assert_eq!(index as usize, (&kmer).into());
519 }
520 }
521 #[test]
522 fn pushl_test() {
523 let k = kmer!("ACGT");
524 let k1 = k.pushl(Dna::G);
525 let k2 = k1.pushl(Dna::A);
526 let k3 = k2.pushl(Dna::T);
527 let k4 = k3.pushl(Dna::C);
528 let k5 = k4.pushl(Dna::C);
529
530 assert_eq!(k1, kmer!("GACG"));
531 assert_eq!(k2, kmer!("AGAC"));
532 assert_eq!(k3, kmer!("TAGA"));
533 assert_eq!(k4, kmer!("CTAG"));
534 assert_eq!(k5, kmer!("CCTA"));
535 }
536 #[test]
537 fn pushr_test() {
538 let k = kmer!("ACGT");
539 let k1 = k.pushr(Dna::G);
540 let k2 = k1.pushr(Dna::A);
541 let k3 = k2.pushr(Dna::T);
542 let k4 = k3.pushr(Dna::C);
543 let k5 = k4.pushr(Dna::C);
544
545 println!("{k1}");
546 assert_eq!(k1, kmer!("CGTG"));
547 assert_eq!(k2, kmer!("GTGA"));
548 assert_eq!(k3, kmer!("TGAT"));
549 assert_eq!(k4, kmer!("GATC"));
550 assert_eq!(k5, kmer!("ATCC"));
551 }
552
553 #[test]
554 #[allow(clippy::cast_sign_loss)]
555 fn amino_kmer_to_usize() {
556 for (kmer, index) in Seq::<Amino>::try_from("SRY")
557 .unwrap()
558 .kmers::<2>()
559 .zip([0b0010_0001_1000, 0b0100_1100_1000])
560 {
561 assert_eq!(index as usize, usize::from(&kmer));
562 }
563 }
564 #[test]
565 fn big_kmer_shiftr() {
566 let mut kmer: Kmer<Dna, 32, u64> = kmer!("AATTTGTGGGTTCGTCTGCGGCTCCGCCCTTA", u64);
567 for base in dna!("TACTATGAGGACGATCAGCACCATAAGAACAAA") {
568 kmer = kmer.pushr(base);
569 }
570 assert_eq!(kmer!("ACTATGAGGACGATCAGCACCATAAGAACAAA", u64), kmer);
571 }
572
573 #[test]
574 fn big_kmer_shiftl() {
575 let mut kmer: Kmer<Dna, 32, u64> = kmer!("AATTTGTGGGTTCGTCTGCGGCTCCGCCCTTA", u64);
576 for base in dna!("GTACTATGAGGACGATCAGCACCATAAGAACAAA") {
577 kmer = kmer.pushl(base);
578 }
579 assert_eq!(kmer!("AAACAAGAATACCACGACTAGCAGGAGTATCA", u64), kmer);
580 }
581
582 #[test]
583 fn amino_kmer_iter() {
584 for (kmer, target) in Seq::<Amino>::try_from("SSLMNHKKL")
585 .unwrap()
586 .kmers::<3>()
587 .zip(["SSL", "SLM", "LMN", "MNH", "NHK", "HKK", "KKL"])
588 {
589 assert_eq!(kmer, target);
590 }
591 }
592
593 #[test]
594 fn test_rotations() {
595 let kmer: Kmer<Dna, 9> = Kmer::try_from(dna!("ACTGCGATG")).unwrap();
596
597 for (shift, rotation) in vec![
598 "ACTGCGATG",
599 "CTGCGATGA",
600 "TGCGATGAC",
601 "GCGATGACT",
602 "CGATGACTG",
603 "GATGACTGC",
604 "ATGACTGCG",
605 "TGACTGCGA",
606 "GACTGCGAT",
607 "ACTGCGATG",
608 "CTGCGATGA",
609 "TGCGATGAC",
610 ]
611 .into_iter()
612 .enumerate()
613 {
614 assert_eq!(kmer.rotated_left(shift as u32), rotation);
616 }
617
618 for (shift, rotation) in vec![
619 "ACTGCGATG",
620 "GACTGCGAT",
621 "TGACTGCGA",
622 "ATGACTGCG",
623 "GATGACTGC",
624 "CGATGACTG",
625 "GCGATGACT",
626 "TGCGATGAC",
627 "CTGCGATGA",
628 "ACTGCGATG",
629 "GACTGCGAT",
630 ]
631 .into_iter()
632 .enumerate()
633 {
634 assert_eq!(kmer.rotated_right(shift as u32), rotation);
636 }
637
638 let kmer: Kmer<Dna, 8> = Kmer::try_from(dna!("ACTGCGAT")).unwrap().rotated_left(1);
639
640 assert_ne!(kmer.to_string(), "ACTGCGAT");
641 assert_eq!(kmer.to_string(), "CTGCGATA");
642
643 let kmer: Kmer<Dna, 8> = kmer!("ACTGCGAT").rotated_right(1);
644
645 assert_ne!(kmer.to_string(), "ACTGCGAT");
646 assert_eq!(kmer.to_string(), "TACTGCGA");
647
648 let kmer: Kmer<Dna, 9> = Kmer::from_str("ACTGCGATG").unwrap().rotated_left(0);
649
650 assert_eq!(kmer.to_string(), "ACTGCGATG");
651 assert_ne!(kmer.to_string(), "ACTGCGATGA");
652
653 let kmer: Kmer<Dna, 9> = Kmer::try_from(dna!("ACTGCGATG")).unwrap().rotated_right(0);
654
655 assert_eq!(kmer.to_string(), "ACTGCGATG");
656 assert_ne!(kmer.to_string(), "ACTGCGATGA");
657
658 let kmer: Kmer<Dna, 9> = Kmer::from_str("ACTGCGATG").unwrap().rotated_left(9 * 3307);
659
660 assert_eq!(kmer.to_string(), "ACTGCGATG");
661 assert_ne!(kmer.to_string(), "ACTGCGATGA");
662
663 let kmer: Kmer<Dna, 9> = kmer!("ACTGCGATG").rotated_right(9 * 3307);
664
665 assert_eq!(kmer.to_string(), "ACTGCGATG");
666 assert_ne!(kmer.to_string(), "ACTGCGATGA");
667 }
668
669 #[test]
670 fn eq_functions() {
671 assert_eq!(kmer!("ACGT"), dna!("ACGT"));
672
673 let kmer: Kmer<Iupac, 4> = Kmer::from_str("ACGT").unwrap();
677 assert_eq!(kmer, iupac!("ACGT"));
678 assert_ne!(kmer, iupac!("NCGT"));
679 }
680
681 #[test]
682 fn kmer_iter() {
683 let cs: Vec<Kmer<Dna, 3>> = dna!("ACTGA").kmers().collect();
685 assert_eq!(cs[0], "ACT");
686 assert_eq!(cs[1], "CTG");
687 assert_eq!(cs[2], "TGA");
688 assert_eq!(cs.len(), 3);
689 }
690
691 #[test]
692 fn k_check() {
693 let _kmer = Kmer::<Dna, 32>::from(0);
694 let _kmer = Kmer::<Amino, 10>::from(0);
695 let _kmer = Kmer::<Iupac, 14>::from(0);
696 }
697
698 #[test]
699 fn kmer_revcomp() {
700 assert_eq!(kmer!("ACGT"), kmer!("ACGT").to_revcomp());
701 assert_ne!(kmer!("GTCGTA"), kmer!("TACGAC"));
702
703 let rc = kmer!("GTCGTA").to_revcomp();
704
705 assert_eq!(rc, kmer!("TACGAC"));
706
707 assert_eq!(
708 kmer!("GCTATCGATCTGATCG"),
709 kmer!("CGATCAGATCGATAGC").to_revcomp()
710 );
711 }
712
713 #[test]
714 fn kmer_deref() {
715 let kmer: Kmer<Dna, 3> = kmer!("ACG");
716 let seq: &SeqSlice<Dna> = &kmer;
717
718 assert_eq!(*seq, *kmer);
719 assert_eq!(seq.to_string(), "ACG");
720
721 let kmer: Kmer<Dna, 8> = kmer!("AAAAAAAA");
722 let seq: &SeqSlice<Dna> = &kmer;
723
724 assert_eq!(seq.to_string(), "AAAAAAAA");
725
726 let kmer: Kmer<Dna, 8> = kmer!("TTTTTTTT");
727 let seq: &SeqSlice<Dna> = &kmer;
728
729 assert_eq!(seq.to_string(), "TTTTTTTT");
730
731 let kmer: Kmer<Dna, 16> = kmer!("AGCTAGCTAGCTAGCT");
732 let seq: &SeqSlice<Dna> = &kmer;
733
734 assert_eq!(seq.to_string(), "AGCTAGCTAGCTAGCT");
735 }
736
737 #[test]
738 fn kmer_as_ref() {
739 let kmer: Kmer<Dna, 4> = kmer!("ACGT");
740 let seq: &SeqSlice<Dna> = kmer.as_ref();
741
742 assert_eq!(seq.to_string(), "ACGT");
743
744 let kmer: Kmer<Dna, 16> = kmer!("AGCTAGCTAGCTAGCT");
745 let seq: &SeqSlice<Dna> = kmer.as_ref();
746
747 assert_eq!(seq.to_string(), "AGCTAGCTAGCTAGCT");
748 }
749
750 #[test]
751 fn kmer_rev() {
752 let mut kmer: Kmer<Dna, 4> = kmer!("ACGT");
753
754 kmer.rev();
755
756 assert_eq!(kmer.to_string(), "TGCA");
757
758 kmer.rev();
759
760 assert_eq!(kmer.to_string(), "ACGT");
761
762 kmer.rev();
763
764 assert_eq!(kmer.to_string(), "TGCA");
765 }
766
767 #[test]
768 #[allow(clippy::needless_borrow)]
769 fn kmer_storage_types() {
770 let s1 = "AACGTAGCCGCGAACTTACGTAGCCGCGAAAA";
771 let s2 = "AACGTAGCCGCGAACTTACGTAGCCGCGAAA";
772 let s3 = "ACGTAGCCGCGAACTTACGTAGCCGCGAAAA";
773
774 let s4 = "AACGTAGCCGCGAACTTACGTAGCCGCGAAAAAACGTAGCCGCGAACTTACGTAGCCGCGAAAA";
775 let s5 = "AACGTAGCCGCGAACTTACGTAGCCGCGAAAAAACGTAGCCGCGAACTTACGTAGCCGCGAAAAA";
776
777 assert_eq!(s1.len(), 32);
778 assert_eq!(s2.len(), 31);
779 assert_eq!(s3.len(), 31);
780 assert_eq!(s4.len(), 64);
781 assert_eq!(s5.len(), 65);
782
783 let kmer1_64 = Kmer::<Dna, 32, u64>::from_str(&s1).unwrap();
784 let kmer2_64 = Kmer::<Dna, 31, u64>::from_str(&s2).unwrap();
785 let kmer3_64 = Kmer::<Dna, 31, u64>::from_str(&s3).unwrap();
786
787 let kmer1 = Kmer::<Dna, 32, u64>::from_str(&s1).unwrap();
788 let kmer2 = Kmer::<Dna, 31, u64>::from_str(&s2).unwrap();
789 let kmer3 = Kmer::<Dna, 31, u64>::from_str(&s3).unwrap();
790
791 let kmer4_128 = Kmer::<Dna, 64, u128>::from_str(&s4).unwrap();
792
793 let seq5: Seq<Dna> = s5.try_into().unwrap();
794
795 assert_eq!(kmer4_128, &seq5[..64]);
796 assert_ne!(kmer4_128, &seq5[1..]);
797
798 assert_eq!(kmer1, &seq5[..32]);
799 assert_eq!(kmer1, &seq5[32..64]);
800
801 assert_eq!(kmer1_64, &seq5[..32]);
802 assert_eq!(kmer1_64, &seq5[32..64]);
803
804 assert_ne!(kmer1, &seq5[..31]);
805 assert_ne!(kmer1, &seq5[32..]);
806
807 assert_ne!(kmer1_64, &seq5[1..33]);
808 assert_ne!(kmer1_64, &seq5[33..]);
809
810 assert_eq!(kmer4_128, kmer4_128);
811 assert_eq!(kmer1_64, kmer1_64);
812 assert_eq!(kmer2, kmer2);
813
814 assert_ne!(kmer2, kmer3);
815 assert_ne!(kmer2_64, kmer3_64);
816 }
823
824 #[test]
825 fn try_from_seq() {
826 let seq: Seq<Dna> = Seq::try_from("ACACACACACACGT").unwrap();
827 assert_eq!(
828 Kmer::<Dna, 8>::try_from(&seq[..8]).unwrap().to_string(),
829 "ACACACAC"
830 );
831 assert_eq!(
832 Kmer::<Dna, 8>::try_from(&seq[1..9]).unwrap().to_string(),
833 "CACACACA"
834 );
835
836 let err: Result<Kmer<Dna, 8>, ParseBioError> = Kmer::try_from(&seq[2..9]);
837 assert_eq!(err, Err(ParseBioError::MismatchedLength(8, 7)));
838
839 let err: Result<Kmer<Dna, 8>, ParseBioError> = Kmer::try_from(seq);
840 assert_eq!(err, Err(ParseBioError::MismatchedLength(8, 14)));
841
842 let seq: Seq<Dna> = Seq::try_from("ACACACACACACGT").unwrap();
843
844 assert_eq!(
845 Kmer::<Dna, 14>::try_from(seq).unwrap().to_string(),
846 "ACACACACACACGT"
847 );
848 }
849}