omics_coordinate/coordinate/
interbase.rs1use crate::Strand;
4use crate::coordinate::Error;
5use crate::position;
6use crate::position::interbase::Position;
7use crate::strand;
8use crate::system::Base;
9use crate::system::Interbase;
10
11pub type Coordinate = crate::Coordinate<Interbase>;
13
14impl Coordinate {
15    pub fn nudge_forward(self) -> Option<crate::Coordinate<Base>> {
24        let (contig, strand, position) = self.into_parts();
25
26        let position = match strand {
27            Strand::Positive => position
28                .get()
29                .checked_add(1)
30                .and_then(|value| crate::Position::<Base>::try_new(value).ok()),
31            Strand::Negative => crate::Position::<Base>::try_new(position.get()).ok(),
32        }?;
33
34        Some(crate::Coordinate::new(contig, strand, position))
35    }
36
37    pub fn nudge_backward(self) -> Option<crate::Coordinate<Base>> {
46        let (contig, strand, position) = self.into_parts();
47
48        let position = match strand {
49            Strand::Positive => crate::Position::<Base>::try_new(position.get()).ok(),
50            Strand::Negative => position
51                .get()
52                .checked_add(1)
53                .and_then(|value| crate::Position::<Base>::try_new(value).ok()),
54        }?;
55
56        Some(crate::Coordinate::new(contig, strand, position))
57    }
58}
59
60impl crate::coordinate::r#trait::Coordinate<Interbase> for Coordinate {
61    fn try_new(
62        contig: impl Into<crate::Contig>,
63        strand: impl TryInto<crate::Strand, Error = strand::Error>,
64        position: position::Number,
65    ) -> super::Result<Self> {
66        let contig = contig.into();
67        let strand = strand.try_into().map_err(Error::Strand)?;
68        let position = Position::new(position);
69
70        Ok(Self {
71            system: Interbase,
72            contig,
73            strand,
74            position,
75        })
76    }
77}
78
79#[cfg(test)]
80mod tests {
81    use super::*;
82    use crate::base;
83    use crate::position::Number;
84
85    fn create_coordinate(contig: &str, strand: &str, position: Number) -> Coordinate {
86        Coordinate::try_new(contig, strand, position).unwrap()
87    }
88
89    fn create_base_coordinate(contig: &str, strand: &str, position: Number) -> base::Coordinate {
90        base::Coordinate::try_new(contig, strand, position).unwrap()
91    }
92
93    #[test]
94    fn nudge_forward() {
95        let coordinate = create_coordinate("seq0", "+", 0);
96        assert_eq!(
97            coordinate.nudge_forward().unwrap(),
98            create_base_coordinate("seq0", "+", 1)
99        );
100
101        let coordinate = create_coordinate("seq0", "+", 1);
102        assert_eq!(
103            coordinate.nudge_forward().unwrap(),
104            create_base_coordinate("seq0", "+", 2)
105        );
106
107        let coordinate = create_coordinate("seq0", "+", 10);
108        assert_eq!(
109            coordinate.nudge_forward().unwrap(),
110            create_base_coordinate("seq0", "+", 11)
111        );
112
113        let coordinate = create_coordinate("seq0", "+", Number::MAX);
114        assert!(coordinate.nudge_forward().is_none());
115
116        let coordinate = create_coordinate("seq0", "-", 0);
117        assert!(coordinate.nudge_forward().is_none());
118
119        let coordinate = create_coordinate("seq0", "-", 1);
120        assert_eq!(
121            coordinate.nudge_forward().unwrap(),
122            create_base_coordinate("seq0", "-", 1)
123        );
124
125        let coordinate = create_coordinate("seq0", "-", 10);
126        assert_eq!(
127            coordinate.nudge_forward().unwrap(),
128            create_base_coordinate("seq0", "-", 10)
129        );
130
131        let coordinate = create_coordinate("seq0", "-", Number::MAX);
132        assert_eq!(
133            coordinate.nudge_forward().unwrap(),
134            create_base_coordinate("seq0", "-", Number::MAX)
135        );
136    }
137
138    #[test]
139    fn nudge_backward() {
140        let coordinate = create_coordinate("seq0", "+", 0);
141        assert!(coordinate.nudge_backward().is_none());
142
143        let coordinate = create_coordinate("seq0", "+", 1);
144        assert_eq!(
145            coordinate.nudge_backward().unwrap(),
146            create_base_coordinate("seq0", "+", 1)
147        );
148
149        let coordinate = create_coordinate("seq0", "+", 10);
150        assert_eq!(
151            coordinate.nudge_backward().unwrap(),
152            create_base_coordinate("seq0", "+", 10)
153        );
154
155        let coordinate = create_coordinate("seq0", "+", Number::MAX);
156        assert_eq!(
157            coordinate.nudge_backward().unwrap(),
158            create_base_coordinate("seq0", "+", Number::MAX)
159        );
160
161        let coordinate = create_coordinate("seq0", "-", 0);
162        assert_eq!(
163            coordinate.nudge_backward().unwrap(),
164            create_base_coordinate("seq0", "-", 1)
165        );
166
167        let coordinate = create_coordinate("seq0", "-", 1);
168        assert_eq!(
169            coordinate.nudge_backward().unwrap(),
170            create_base_coordinate("seq0", "-", 2)
171        );
172
173        let coordinate = create_coordinate("seq0", "-", 10);
174        assert_eq!(
175            coordinate.nudge_backward().unwrap(),
176            create_base_coordinate("seq0", "-", 11)
177        );
178
179        let coordinate = create_coordinate("seq0", "-", Number::MAX);
180        assert!(coordinate.nudge_backward().is_none());
181    }
182}