omics_coordinate/position/
interbase.rs1use std::num::NonZero;
4
5use crate::position::Error;
6use crate::position::Number;
7use crate::position::ParseError;
8use crate::position::Result;
9use crate::system::Interbase;
10
11mod addition;
12mod subtraction;
13
14const _: () = {
19 assert!(size_of::<Position>() == size_of::<Number>());
22
23 const fn is_copy<T: Copy>() {}
25 is_copy::<Position>();
26};
27
28pub type Position = crate::Position<Interbase>;
36
37impl Position {
38 pub const fn new(value: Number) -> Self {
49 Self {
50 system: Interbase,
51 value,
52 }
53 }
54}
55impl super::r#trait::Position<Interbase> for Position {}
60
61impl std::str::FromStr for Position {
62 type Err = Error;
63
64 fn from_str(s: &str) -> Result<Self> {
65 Ok(Self::new(s.parse::<Number>().map_err(|error| {
66 Error::Parse(ParseError::Int {
67 system: Interbase::NAME,
68 inner: error,
69 value: s.to_string(),
70 })
71 })?))
72 }
73}
74
75macro_rules! position_from_smaller_number {
77 ($from:ty) => {
78 impl From<$from> for Position {
79 fn from(value: $from) -> Self {
80 Self::new(value as Number)
81 }
82 }
83
84 impl From<NonZero<$from>> for Position {
85 fn from(value: NonZero<$from>) -> Self {
86 Self::new(value.get() as Number)
87 }
88 }
89 };
90}
91
92#[cfg(feature = "position-u64")]
93position_from_smaller_number!(u64);
94position_from_smaller_number!(u32);
95position_from_smaller_number!(u16);
96position_from_smaller_number!(u8);
97
98#[cfg(test)]
99mod tests {
100 use std::num::NonZeroU8;
101 use std::num::NonZeroU16;
102 #[cfg(feature = "position-u64")]
103 use std::num::NonZeroU32;
104
105 use crate::Position;
106 use crate::position::Number;
107 use crate::position::Result;
108 use crate::system::Interbase;
109
110 #[test]
111 fn try_from_number() {
112 let position: Position<Interbase> = 1u32.into();
113 assert_eq!(position.get(), 1);
114 }
115
116 #[test]
117 fn distance() {
118 let a = Position::<Interbase>::new(10);
120 let b = Position::<Interbase>::new(10);
121 assert_eq!(a.distance_unchecked(&b), 0);
122 assert_eq!(b.distance_unchecked(&a), 0);
123
124 let a = Position::<Interbase>::new(Number::MAX);
126 let b = Position::<Interbase>::new(0);
127 assert_eq!(a.distance_unchecked(&b), Number::MAX);
128 assert_eq!(b.distance_unchecked(&a), Number::MAX);
129 }
130
131 #[test]
132 fn parse() {
133 let zero = "0".parse::<Position<Interbase>>().unwrap();
134 assert_eq!(zero.get(), 0);
135
136 let position = "1".parse::<Position<Interbase>>().unwrap();
137 assert_eq!(position.get(), 1);
138
139 let err = "a".parse::<Position<Interbase>>().unwrap_err();
140 assert_eq!(
141 err.to_string(),
142 "parse error: failed to parse interbase coordinate system position from `a`: invalid \
143 digit found in string"
144 );
145 }
146
147 #[test]
148 fn from_smaller_types() -> Result<()> {
149 #[cfg(feature = "position-u64")]
150 {
151 let position = Position::<Interbase>::from(0u32);
153 assert_eq!(position.get(), 0);
154
155 let position = Position::<Interbase>::from(NonZeroU32::new(1).unwrap());
156 assert_eq!(position.get(), 1);
157 }
158
159 let position = Position::<Interbase>::from(0u16);
161 assert_eq!(position.get(), 0);
162
163 let position = Position::<Interbase>::from(NonZeroU16::new(1).unwrap());
164 assert_eq!(position.get(), 1);
165
166 let position = Position::<Interbase>::from(0u8);
168 assert_eq!(position.get(), 0);
169
170 let position = Position::<Interbase>::from(NonZeroU8::new(1).unwrap());
171 assert_eq!(position.get(), 1);
172
173 Ok(())
174 }
175}