Skip to main content

raknet_rust/protocol/
sequence24.rs

1use std::cmp::Ordering;
2use std::ops::Add;
3
4use bytes::{Buf, BufMut};
5
6use crate::error::{DecodeError, EncodeError};
7
8use super::codec::RaknetCodec;
9use super::primitives::U24Le;
10
11const MODULO: u32 = 1 << 24;
12const MASK: u32 = MODULO - 1;
13const HALF: u32 = MODULO / 2;
14
15#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
16pub struct Sequence24(u32);
17
18impl Sequence24 {
19    pub fn new(value: u32) -> Self {
20        Self(value & MASK)
21    }
22
23    pub fn value(self) -> u32 {
24        self.0 & MASK
25    }
26
27    pub fn next(self) -> Self {
28        Self::new(self.value() + 1)
29    }
30
31    pub fn prev(self) -> Self {
32        if self.value() == 0 {
33            Self::new(MASK)
34        } else {
35            Self::new(self.value() - 1)
36        }
37    }
38
39    pub fn distance_to(self, newer: Sequence24) -> u32 {
40        let cur = self.value();
41        let target = newer.value();
42        if target >= cur {
43            target - cur
44        } else {
45            MODULO - cur + target
46        }
47    }
48}
49
50impl Ord for Sequence24 {
51    fn cmp(&self, other: &Self) -> Ordering {
52        let a = self.value() as i32;
53        let b = other.value() as i32;
54        let delta = a.wrapping_sub(b);
55
56        if delta == 0 {
57            Ordering::Equal
58        } else if (delta > 0 && delta < HALF as i32) || (delta < 0 && delta < -(HALF as i32)) {
59            Ordering::Greater
60        } else {
61            Ordering::Less
62        }
63    }
64}
65
66impl PartialOrd for Sequence24 {
67    fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
68        Some(self.cmp(other))
69    }
70}
71
72impl Add for Sequence24 {
73    type Output = Sequence24;
74
75    fn add(self, rhs: Self) -> Self::Output {
76        Sequence24::new((self.value() + rhs.value()) % MODULO)
77    }
78}
79
80impl Add<i32> for Sequence24 {
81    type Output = Sequence24;
82
83    fn add(self, rhs: i32) -> Self::Output {
84        let mut value = self.value() as i32 + rhs;
85        value %= MODULO as i32;
86        if value < 0 {
87            value += MODULO as i32;
88        }
89        Sequence24::new(value as u32)
90    }
91}
92
93impl RaknetCodec for Sequence24 {
94    fn encode_raknet(&self, dst: &mut impl BufMut) -> Result<(), EncodeError> {
95        U24Le(self.value()).encode_raknet(dst)
96    }
97
98    fn decode_raknet(src: &mut impl Buf) -> Result<Self, DecodeError> {
99        Ok(Sequence24::new(U24Le::decode_raknet(src)?.0))
100    }
101}