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