naia_shared/
wrapping_number.rs1pub fn sequence_greater_than(s1: u16, s2: u16) -> bool {
6 ((s1 > s2) && (s1 - s2 <= 32768)) || ((s1 < s2) && (s2 - s1 > 32768))
7}
8
9pub fn sequence_less_than(s1: u16, s2: u16) -> bool {
14 sequence_greater_than(s2, s1)
15}
16
17pub fn wrapping_diff(a: u16, b: u16) -> i16 {
23 const MAX: i32 = std::i16::MAX as i32;
24 const MIN: i32 = std::i16::MIN as i32;
25 const ADJUST: i32 = (std::u16::MAX as i32) + 1;
26
27 let a: i32 = i32::from(a);
28 let b: i32 = i32::from(b);
29
30 let mut result = b - a;
31 if (MIN..=MAX).contains(&result) {
32 result as i16
33 } else if b > a {
34 result = b - (a + ADJUST);
35 if (MIN..=MAX).contains(&result) {
36 result as i16
37 } else {
38 panic!("integer overflow, this shouldn't happen")
39 }
40 } else {
41 result = (b + ADJUST) - a;
42 if (MIN..=MAX).contains(&result) {
43 result as i16
44 } else {
45 panic!("integer overflow, this shouldn't happen")
46 }
47 }
48}
49
50#[cfg(test)]
51mod sequence_compare_tests {
52 use super::{sequence_greater_than, sequence_less_than};
53
54 #[test]
55 fn greater_is_greater() {
56 assert!(sequence_greater_than(2, 1));
57 }
58
59 #[test]
60 fn greater_is_not_equal() {
61 assert!(!sequence_greater_than(2, 2));
62 }
63
64 #[test]
65 fn greater_is_not_less() {
66 assert!(!sequence_greater_than(1, 2));
67 }
68
69 #[test]
70 fn less_is_less() {
71 assert!(sequence_less_than(1, 2));
72 }
73
74 #[test]
75 fn less_is_not_equal() {
76 assert!(!sequence_less_than(2, 2));
77 }
78
79 #[test]
80 fn less_is_not_greater() {
81 assert!(!sequence_less_than(2, 1));
82 }
83}
84
85#[cfg(test)]
86mod wrapping_diff_tests {
87 use super::wrapping_diff;
88
89 #[test]
90 fn simple() {
91 let a: u16 = 10;
92 let b: u16 = 12;
93
94 let result = wrapping_diff(a, b);
95
96 assert_eq!(result, 2);
97 }
98
99 #[test]
100 fn simple_backwards() {
101 let a: u16 = 10;
102 let b: u16 = 12;
103
104 let result = wrapping_diff(b, a);
105
106 assert_eq!(result, -2);
107 }
108
109 #[test]
110 fn max_wrap() {
111 let a: u16 = std::u16::MAX;
112 let b: u16 = a.wrapping_add(2);
113
114 let result = wrapping_diff(a, b);
115
116 assert_eq!(result, 2);
117 }
118
119 #[test]
120 fn min_wrap() {
121 let a: u16 = 0;
122 let b: u16 = a.wrapping_sub(2);
123
124 let result = wrapping_diff(a, b);
125
126 assert_eq!(result, -2);
127 }
128
129 #[test]
130 fn max_wrap_backwards() {
131 let a: u16 = std::u16::MAX;
132 let b: u16 = a.wrapping_add(2);
133
134 let result = wrapping_diff(b, a);
135
136 assert_eq!(result, -2);
137 }
138
139 #[test]
140 fn min_wrap_backwards() {
141 let a: u16 = 0;
142 let b: u16 = a.wrapping_sub(2);
143
144 let result = wrapping_diff(b, a);
145
146 assert_eq!(result, 2);
147 }
148
149 #[test]
150 fn medium_min_wrap() {
151 let diff: u16 = std::u16::MAX / 2;
152 let a: u16 = 0;
153 let b: u16 = a.wrapping_sub(diff);
154
155 let result = i32::from(wrapping_diff(a, b));
156
157 assert_eq!(result, -i32::from(diff));
158 }
159
160 #[test]
161 fn medium_min_wrap_backwards() {
162 let diff: u16 = std::u16::MAX / 2;
163 let a: u16 = 0;
164 let b: u16 = a.wrapping_sub(diff);
165
166 let result = i32::from(wrapping_diff(b, a));
167
168 assert_eq!(result, i32::from(diff));
169 }
170
171 #[test]
172 fn medium_max_wrap() {
173 let diff: u16 = std::u16::MAX / 2;
174 let a: u16 = std::u16::MAX;
175 let b: u16 = a.wrapping_add(diff);
176
177 let result = i32::from(wrapping_diff(a, b));
178
179 assert_eq!(result, i32::from(diff));
180 }
181
182 #[test]
183 fn medium_max_wrap_backwards() {
184 let diff: u16 = std::u16::MAX / 2;
185 let a: u16 = std::u16::MAX;
186 let b: u16 = a.wrapping_add(diff);
187
188 let result = i32::from(wrapping_diff(b, a));
189
190 assert_eq!(result, -i32::from(diff));
191 }
192}