Skip to main content

vexil_runtime/
zigzag.rs

1pub fn zigzag_encode(n: i64, type_bits: u8) -> u64 {
2    ((n << 1) ^ (n >> (u32::from(type_bits) - 1))) as u64
3}
4
5pub fn zigzag_decode(n: u64) -> i64 {
6    ((n >> 1) as i64) ^ -((n & 1) as i64)
7}
8
9#[cfg(test)]
10mod tests {
11    use super::*;
12
13    #[test]
14    fn encode_mapping() {
15        assert_eq!(zigzag_encode(0, 64), 0);
16        assert_eq!(zigzag_encode(-1, 64), 1);
17        assert_eq!(zigzag_encode(1, 64), 2);
18        assert_eq!(zigzag_encode(-2, 64), 3);
19        assert_eq!(zigzag_encode(2, 64), 4);
20        assert_eq!(zigzag_encode(i64::MIN, 64), u64::MAX);
21        assert_eq!(zigzag_encode(i64::MAX, 64), u64::MAX - 1);
22    }
23
24    #[test]
25    fn round_trip_i32_range() {
26        for &v in &[0i64, 1, -1, 127, -128, i32::MIN as i64, i32::MAX as i64] {
27            let encoded = zigzag_encode(v, 32);
28            let decoded = zigzag_decode(encoded);
29            assert_eq!(decoded, v, "round-trip failed for {v}");
30        }
31    }
32
33    #[test]
34    fn encode_32bit_width() {
35        assert_eq!(zigzag_encode(-1, 32), 1);
36        assert_eq!(zigzag_encode(1, 32), 2);
37    }
38}