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 inner: error,
68 value: s.to_string(),
69 })
70 })?))
71 }
72}
73
74macro_rules! position_from_smaller_number {
76 ($from:ty) => {
77 impl From<$from> for Position {
78 fn from(value: $from) -> Self {
79 Self::new(value as Number)
80 }
81 }
82
83 impl From<NonZero<$from>> for Position {
84 fn from(value: NonZero<$from>) -> Self {
85 Self::new(value.get() as Number)
86 }
87 }
88 };
89}
90
91#[cfg(feature = "position-u64")]
92position_from_smaller_number!(u64);
93position_from_smaller_number!(u32);
94position_from_smaller_number!(u16);
95position_from_smaller_number!(u8);
96
97#[cfg(test)]
98mod tests {
99 use std::num::NonZeroU8;
100 use std::num::NonZeroU16;
101 #[cfg(feature = "position-u64")]
102 use std::num::NonZeroU32;
103
104 use crate::Position;
105 use crate::position::Number;
106 use crate::position::Result;
107 use crate::system::Interbase;
108
109 #[test]
110 fn try_from_number() {
111 let position: Position<Interbase> = 1u32.into();
112 assert_eq!(position.get(), 1);
113 }
114
115 #[test]
116 fn distance() {
117 let a = Position::<Interbase>::new(10);
119 let b = Position::<Interbase>::new(10);
120 assert_eq!(a.distance_unchecked(&b), 0);
121 assert_eq!(b.distance_unchecked(&a), 0);
122
123 let a = Position::<Interbase>::new(Number::MAX);
125 let b = Position::<Interbase>::new(0);
126 assert_eq!(a.distance_unchecked(&b), Number::MAX);
127 assert_eq!(b.distance_unchecked(&a), Number::MAX);
128 }
129
130 #[test]
131 fn parse() {
132 let zero = "0".parse::<Position<Interbase>>().unwrap();
133 assert_eq!(zero.get(), 0);
134
135 let position = "1".parse::<Position<Interbase>>().unwrap();
136 assert_eq!(position.get(), 1);
137
138 let err = "a".parse::<Position<Interbase>>().unwrap_err();
139 assert_eq!(
140 err.to_string(),
141 "parse error: invalid digit found in string: `a`"
142 );
143 }
144
145 #[test]
146 fn from_smaller_types() -> Result<()> {
147 #[cfg(feature = "position-u64")]
148 {
149 let position = Position::<Interbase>::from(0u32);
151 assert_eq!(position.get(), 0);
152
153 let position = Position::<Interbase>::from(NonZeroU32::new(1).unwrap());
154 assert_eq!(position.get(), 1);
155 }
156
157 let position = Position::<Interbase>::from(0u16);
159 assert_eq!(position.get(), 0);
160
161 let position = Position::<Interbase>::from(NonZeroU16::new(1).unwrap());
162 assert_eq!(position.get(), 1);
163
164 let position = Position::<Interbase>::from(0u8);
166 assert_eq!(position.get(), 0);
167
168 let position = Position::<Interbase>::from(NonZeroU8::new(1).unwrap());
169 assert_eq!(position.get(), 1);
170
171 Ok(())
172 }
173}