raknet_rust/protocol/
sequence24.rs1use 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}