veloren_network_protocol/
types.rs

1use bitflags::bitflags;
2use bytes::{Buf, BufMut, BytesMut};
3use rand::Rng;
4
5/// MessageID, unique ID per Message.
6pub type Mid = u64;
7/// ChannelID, unique ID per Channel (Protocol)
8pub type Cid = u64;
9/// Every Stream has a `Prio` and guaranteed [`Bandwidth`].
10/// Every send, the guarantees part is used first.
11/// If there is still bandwidth left, it will be shared by all Streams with the
12/// same priority. Prio 0 will be send first, then 1, ... till the last prio 7
13/// is send. Prio must be < 8!
14///
15/// [`Bandwidth`]: crate::Bandwidth
16pub type Prio = u8;
17/// guaranteed `Bandwidth`. See [`Prio`]
18///
19/// [`Prio`]: crate::Prio
20pub type Bandwidth = u64;
21
22bitflags! {
23    /// use promises to modify the behavior of [`Streams`].
24    /// see the consts in this `struct` for
25    ///
26    /// [`Streams`]: crate::api::Stream
27    #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
28    pub struct Promises: u8 {
29        /// this will guarantee that the order of messages which are send on one side,
30        /// is the same when received on the other.
31        const ORDERED = 0b00000001;
32        /// this will guarantee that messages received haven't been altered by errors,
33        /// like bit flips, this is done with a checksum.
34        const CONSISTENCY = 0b00000010;
35        /// this will guarantee that the other side will receive every message exactly
36        /// once no messages are dropped
37        const GUARANTEED_DELIVERY = 0b00000100;
38        /// this will enable the internal compression on this, only useable with #[cfg(feature = "compression")]
39        /// [`Stream`](crate::api::Stream)
40        const COMPRESSED = 0b00001000;
41        /// this will enable the internal encryption on this
42        /// [`Stream`](crate::api::Stream)
43        const ENCRYPTED = 0b00010000;
44    }
45}
46
47impl Promises {
48    pub const fn to_le_bytes(self) -> [u8; 1] { self.bits().to_le_bytes() }
49}
50
51pub(crate) const VELOREN_MAGIC_NUMBER: [u8; 7] = *b"VELOREN";
52/// When this semver differs, 2 Networks can't communicate.
53pub const VELOREN_NETWORK_VERSION: [u32; 3] = [0, 6, 0];
54pub(crate) const STREAM_ID_OFFSET1: Sid = Sid::new(0);
55pub(crate) const STREAM_ID_OFFSET2: Sid = Sid::new(u64::MAX / 2);
56/// Maximal possible Prio to choose (for performance reasons)
57pub const HIGHEST_PRIO: u8 = 7;
58
59/// Support struct used for uniquely identifying `Participant` over the
60/// `Network`.
61#[derive(PartialEq, Eq, Hash, Clone, Copy)]
62pub struct Pid {
63    internal: u128,
64}
65
66/// Unique ID per Stream, in one Channel.
67/// one side will always start with 0, while the other start with u64::MAX / 2.
68/// number increases for each created Stream.
69#[derive(PartialEq, Eq, Hash, Clone, Copy, PartialOrd, Ord)]
70pub struct Sid {
71    internal: u64,
72}
73
74impl Pid {
75    /// create a new Pid with a random interior value
76    ///
77    /// # Example
78    /// ```rust
79    /// use veloren_network_protocol::Pid;
80    ///
81    /// let pid = Pid::new();
82    /// ```
83    pub fn new() -> Self {
84        Self {
85            internal: rand::thread_rng().gen(),
86        }
87    }
88
89    /// don't use fake! just for testing!
90    /// This will panic if pid i greater than 7, as I do not want you to use
91    /// this in production!
92    #[doc(hidden)]
93    pub fn fake(pid_offset: u8) -> Self {
94        assert!(pid_offset < 8);
95        let o = pid_offset as u128;
96        const OFF: [u128; 5] = [
97            0x40,
98            0x40 * 0x40,
99            0x40 * 0x40 * 0x40,
100            0x40 * 0x40 * 0x40 * 0x40,
101            0x40 * 0x40 * 0x40 * 0x40 * 0x40,
102        ];
103        Self {
104            internal: o + o * OFF[0] + o * OFF[1] + o * OFF[2] + o * OFF[3] + o * OFF[4],
105        }
106    }
107
108    #[inline]
109    pub(crate) fn from_bytes(bytes: &mut BytesMut) -> Self {
110        Self {
111            internal: bytes.get_u128_le(),
112        }
113    }
114
115    #[inline]
116    pub(crate) fn to_bytes(self, bytes: &mut BytesMut) { bytes.put_u128_le(self.internal) }
117}
118
119impl Sid {
120    pub const fn new(internal: u64) -> Self { Self { internal } }
121
122    pub fn get_u64(&self) -> u64 { self.internal }
123
124    #[inline]
125    pub(crate) fn from_bytes(bytes: &mut BytesMut) -> Self {
126        Self {
127            internal: bytes.get_u64_le(),
128        }
129    }
130
131    #[inline]
132    pub(crate) fn to_bytes(self, bytes: &mut BytesMut) { bytes.put_u64_le(self.internal) }
133}
134
135impl std::fmt::Debug for Pid {
136    #[inline]
137    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
138        const BITS_PER_SIXLET: usize = 6;
139        //only print last 6 chars of number as full u128 logs are unreadable
140        const CHAR_COUNT: usize = 6;
141        for i in 0..CHAR_COUNT {
142            write!(
143                f,
144                "{}",
145                sixlet_to_str((self.internal >> (i * BITS_PER_SIXLET)) & 0x3F)
146            )?;
147        }
148        Ok(())
149    }
150}
151
152impl Default for Pid {
153    fn default() -> Self { Pid::new() }
154}
155
156impl std::fmt::Display for Pid {
157    #[inline]
158    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { write!(f, "{:?}", self) }
159}
160
161impl std::ops::AddAssign for Sid {
162    fn add_assign(&mut self, other: Self) {
163        *self = Self {
164            internal: self.internal + other.internal,
165        };
166    }
167}
168
169impl std::fmt::Debug for Sid {
170    #[inline]
171    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
172        //only print last 6 chars of number as full u128 logs are unreadable
173        write!(f, "{}", self.internal.rem_euclid(1000000))
174    }
175}
176
177impl From<u64> for Sid {
178    fn from(internal: u64) -> Self { Sid { internal } }
179}
180
181impl std::fmt::Display for Sid {
182    #[inline]
183    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
184        write!(f, "{}", self.internal)
185    }
186}
187
188fn sixlet_to_str(sixlet: u128) -> char {
189    b"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"[sixlet as usize] as char
190}
191
192#[cfg(test)]
193mod tests {
194    use super::*;
195
196    #[test]
197    fn frame_creation() {
198        Pid::new();
199        assert_eq!(format!("{}", Pid::fake(0)), "AAAAAA");
200        assert_eq!(format!("{}", Pid::fake(1)), "BBBBBB");
201        assert_eq!(format!("{}", Pid::fake(2)), "CCCCCC");
202    }
203
204    #[test]
205    fn test_sixlet_to_str() {
206        assert_eq!(sixlet_to_str(0), 'A');
207        assert_eq!(sixlet_to_str(29), 'd');
208        assert_eq!(sixlet_to_str(63), '/');
209    }
210}