rsvart/ops/
transposable.rs1use crate::genomic::{Contiged, Strand, Stranded};
2use crate::ops::{Located, Unit};
3
4pub trait Transposable<C> {
5 fn start_on_strand(&self, strand: Strand) -> C;
6
7 fn end_on_strand(&self, strand: Strand) -> C;
8}
9
10impl<C, T> Transposable<C> for T
11where
12 C: Unit,
13 T: Contiged<C> + Located<C> + Stranded,
14{
15 fn start_on_strand(&self, strand: Strand) -> C {
16 match self.strand().eq(&strand) {
17 true => *self.start(),
18 false => *self.contig().end() - *self.end(),
19 }
20 }
21
22 fn end_on_strand(&self, strand: Strand) -> C {
23 match self.strand().eq(&strand) {
24 true => *self.end(),
25 false => *self.contig().end() - *self.start(),
26 }
27 }
28}
29
30#[cfg(test)]
31mod test {
32 use super::*;
33 use crate::genomic::{AssignedMoleculeType, Contig, SequenceRole};
34 use rstest::rstest;
35
36 #[derive(PartialEq, Eq)]
37 struct TestRegion {
38 strand: Strand,
39 start: u8,
40 end: u8,
41 contig: Contig<u8>,
42 }
43
44 impl Stranded for TestRegion {
45 fn strand(&self) -> Strand {
46 self.strand
47 }
48 }
49
50 impl Located<u8> for TestRegion {
51 fn start(&self) -> &u8 {
52 &self.start
53 }
54
55 fn end(&self) -> &u8 {
56 &self.end
57 }
58 }
59
60 impl Contiged<u8> for TestRegion {
61 type Contig = Contig<u8>;
62
63 fn contig(&self) -> &Self::Contig {
64 &self.contig
65 }
66 }
67 fn get_test_contig() -> Contig<u8> {
68 Contig::new(
69 "1".to_string(),
70 SequenceRole::AssembledMolecule,
71 "1".to_string(),
72 AssignedMoleculeType::Chromosome,
73 249,
74 "CM000663.1".to_string(),
75 "NC_000001.10".to_string(),
76 "chr1".to_string(),
77 )
78 .unwrap()
79 }
80 #[rstest]
81 fn test_start_on_strand() {
82 let contig = get_test_contig();
83 let test_region = TestRegion {
84 strand: Strand::Reverse,
85 start: 32,
86 end: 200,
87 contig,
88 };
89 assert_eq!(
90 test_region.start_on_strand(Strand::Reverse),
91 *test_region.start()
92 );
93 assert_eq!(test_region.start_on_strand(Strand::Forward), 49);
94 }
95
96 #[rstest]
97 fn test_end_on_strand() {
98 let contig = get_test_contig();
99 let test_region = TestRegion {
100 strand: Strand::Reverse,
101 start: 32,
102 end: 200,
103 contig,
104 };
105 assert_eq!(
106 test_region.end_on_strand(Strand::Reverse),
107 *test_region.end()
108 );
109 assert_eq!(test_region.end_on_strand(Strand::Forward), 217);
110 }
111}