naia_shared/world/component/
diff_mask.rs

1use std::fmt;
2
3// The DiffMask is a variable-length byte array, where each bit represents
4// the current state of a Property owned by a Replica.
5// The Property tracks whether it has been updated and needs to be synced
6// with the remote Client
7#[derive(PartialEq, Eq, Clone, Debug)]
8pub struct DiffMask {
9    mask: Vec<u8>,
10}
11
12impl DiffMask {
13    /// Create a new DiffMask with a given number of bytes
14    pub fn new(bytes: u8) -> DiffMask {
15        DiffMask {
16            mask: vec![0; bytes as usize],
17        }
18    }
19
20    /// Gets the bit at the specified position within the DiffMask
21    pub fn bit(&self, index: u8) -> Option<bool> {
22        if let Some(byte) = self.mask.get((index / 8) as usize) {
23            let adjusted_index = index % 8;
24            return Some(byte & (1 << adjusted_index) != 0);
25        }
26
27        None
28    }
29
30    /// Sets the bit at the specified position within the DiffMask
31    pub fn set_bit(&mut self, index: u8, value: bool) {
32        if let Some(byte) = self.mask.get_mut((index / 8) as usize) {
33            let adjusted_index = index % 8;
34            let bit_mask = 1 << adjusted_index;
35            if value {
36                *byte |= bit_mask;
37            } else {
38                *byte &= !bit_mask;
39            }
40        }
41    }
42
43    /// Clears the whole DiffMask
44    pub fn clear(&mut self) {
45        let size = self.mask.len();
46        self.mask = vec![0; size];
47    }
48
49    /// Returns whether any bit has been set in the DiffMask
50    pub fn is_clear(&self) -> bool {
51        for byte in self.mask.iter() {
52            if *byte != 0 {
53                return false;
54            }
55        }
56        true
57    }
58
59    /// Get the number of bytes required to represent the DiffMask
60    pub fn byte_number(&self) -> u8 {
61        self.mask.len() as u8
62    }
63
64    /// Gets a byte at the specified index in the DiffMask
65    pub fn byte(&self, index: usize) -> u8 {
66        self.mask[index]
67    }
68
69    /// Performs a NAND operation on the DiffMask, with another DiffMask
70    pub fn nand(&mut self, other: &DiffMask) {
71        // NOTE: this is not actually a NAND operation, but a "AND NOT" operation
72
73        //if other diff mask has different capacity, do nothing
74        if other.byte_number() != self.byte_number() {
75            return;
76        }
77
78        for n in 0..self.mask.len() {
79            if let Some(my_byte) = self.mask.get_mut(n) {
80                let other_byte = !other.byte(n);
81                *my_byte &= other_byte;
82            }
83        }
84    }
85
86    /// Performs an OR operation on the DiffMask, with another DiffMask
87    pub fn or(&mut self, other: &DiffMask) {
88        //if other diff mask has different capacity, do nothing
89        if other.byte_number() != self.byte_number() {
90            return;
91        }
92
93        for n in 0..self.mask.len() {
94            if let Some(my_byte) = self.mask.get_mut(n) {
95                let other_byte = other.byte(n);
96                *my_byte |= other_byte;
97            }
98        }
99    }
100
101    /// Copies the DiffMask into another DiffMask
102    pub fn copy_contents(&mut self, other: &DiffMask) {
103        //if other diff mask has different capacity, do nothing
104        if other.byte_number() != self.byte_number() {
105            return;
106        }
107
108        for n in 0..self.mask.len() {
109            if let Some(my_byte) = self.mask.get_mut(n) {
110                let other_byte = other.byte(n);
111                *my_byte = other_byte;
112            }
113        }
114    }
115}
116
117impl fmt::Display for DiffMask {
118    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
119        let mut out_string: String = String::new();
120        for y in 0..8 {
121            if let Some(bit) = self.bit(y) {
122                if bit {
123                    out_string.push('1');
124                } else {
125                    out_string.push('0');
126                }
127            }
128        }
129        write!(f, "{}", out_string)
130    }
131}
132
133#[cfg(test)]
134mod single_byte_tests {
135    use crate::DiffMask;
136
137    #[test]
138    fn getset() {
139        let mut mask = DiffMask::new(1);
140
141        mask.set_bit(0, true);
142        mask.set_bit(2, true);
143        mask.set_bit(4, true);
144        mask.set_bit(6, true);
145        mask.set_bit(4, false);
146
147        assert!(mask.bit(0).unwrap());
148        assert!(!mask.bit(1).unwrap());
149        assert!(mask.bit(2).unwrap());
150        assert!(!mask.bit(4).unwrap());
151        assert!(mask.bit(6).unwrap());
152    }
153
154    #[test]
155    fn clear() {
156        let mut mask = DiffMask::new(1);
157
158        mask.set_bit(0, true);
159        mask.set_bit(2, true);
160        mask.set_bit(4, true);
161        mask.set_bit(6, true);
162
163        mask.clear();
164
165        assert!(!mask.bit(0).unwrap());
166        assert!(!mask.bit(2).unwrap());
167        assert!(!mask.bit(4).unwrap());
168        assert!(!mask.bit(6).unwrap());
169    }
170
171    #[test]
172    fn is_clear_true() {
173        let mut mask = DiffMask::new(1);
174
175        mask.set_bit(2, true);
176
177        assert!(!mask.is_clear());
178
179        mask.set_bit(2, false);
180
181        assert!(mask.is_clear());
182    }
183
184    #[test]
185    fn bytes() {
186        let mask = DiffMask::new(1);
187        assert!(mask.byte_number() == 1);
188    }
189
190    #[test]
191    fn byte() {
192        let mut mask = DiffMask::new(1);
193        mask.set_bit(2, true);
194        let byte = mask.byte(0);
195        assert!(byte == 4);
196    }
197
198    #[test]
199    fn nand() {
200        let mut mask_a = DiffMask::new(1);
201        mask_a.set_bit(1, true);
202        mask_a.set_bit(2, true);
203
204        let mut mask_b = DiffMask::new(1);
205        mask_b.set_bit(1, true);
206
207        mask_a.nand(&mask_b);
208
209        assert!(!mask_a.bit(0).unwrap());
210        assert!(!mask_a.bit(1).unwrap());
211        assert!(mask_a.bit(2).unwrap());
212        assert!(!mask_a.bit(3).unwrap());
213    }
214
215    #[test]
216    fn or() {
217        let mut mask_a = DiffMask::new(1);
218        mask_a.set_bit(1, true);
219        mask_a.set_bit(2, true);
220
221        let mut mask_b = DiffMask::new(1);
222        mask_b.set_bit(2, true);
223        mask_b.set_bit(3, true);
224
225        mask_a.or(&mask_b);
226
227        assert!(!mask_a.bit(0).unwrap());
228        assert!(mask_a.bit(1).unwrap());
229        assert!(mask_a.bit(2).unwrap());
230        assert!(mask_a.bit(3).unwrap());
231        assert!(!mask_a.bit(4).unwrap());
232    }
233
234    #[test]
235    fn clone() {
236        let mut mask_a = DiffMask::new(1);
237        mask_a.set_bit(1, true);
238        mask_a.set_bit(4, true);
239
240        let mask_b = mask_a.clone();
241
242        assert!(mask_b.bit(1).unwrap());
243        assert!(!mask_b.bit(3).unwrap());
244        assert!(mask_b.bit(4).unwrap());
245    }
246}
247
248#[cfg(test)]
249mod double_byte_tests {
250    use crate::DiffMask;
251
252    #[test]
253    fn getset() {
254        let mut mask = DiffMask::new(2);
255
256        mask.set_bit(0, true);
257        mask.set_bit(4, true);
258        mask.set_bit(8, true);
259        mask.set_bit(12, true);
260        mask.set_bit(8, false);
261
262        assert!(mask.bit(0).unwrap());
263        assert!(mask.bit(4).unwrap());
264        assert!(!mask.bit(8).unwrap());
265        assert!(mask.bit(12).unwrap());
266        assert!(!mask.bit(13).unwrap());
267    }
268
269    #[test]
270    fn clear() {
271        let mut mask = DiffMask::new(2);
272
273        mask.set_bit(0, true);
274        mask.set_bit(4, true);
275        mask.set_bit(8, true);
276        mask.set_bit(12, true);
277
278        mask.clear();
279
280        assert!(!mask.bit(0).unwrap());
281        assert!(!mask.bit(4).unwrap());
282        assert!(!mask.bit(8).unwrap());
283        assert!(!mask.bit(12).unwrap());
284    }
285
286    #[test]
287    fn is_clear_true() {
288        let mut mask = DiffMask::new(2);
289
290        mask.set_bit(9, true);
291
292        assert!(!mask.is_clear());
293
294        mask.set_bit(9, false);
295
296        assert!(mask.is_clear());
297    }
298
299    #[test]
300    fn bytes() {
301        let mask = DiffMask::new(2);
302        assert!(mask.byte_number() == 2);
303    }
304
305    #[test]
306    fn byte() {
307        let mut mask = DiffMask::new(2);
308        mask.set_bit(10, true);
309        let byte = mask.byte(1);
310        assert!(byte == 4);
311    }
312
313    #[test]
314    fn nand() {
315        let mut mask_a = DiffMask::new(2);
316        mask_a.set_bit(1, true);
317        mask_a.set_bit(2, true);
318        mask_a.set_bit(9, true);
319        mask_a.set_bit(10, true);
320
321        let mut mask_b = DiffMask::new(2);
322        mask_b.set_bit(1, true);
323        mask_b.set_bit(9, true);
324
325        mask_a.nand(&mask_b);
326
327        assert!(!mask_a.bit(0).unwrap());
328        assert!(!mask_a.bit(1).unwrap());
329        assert!(mask_a.bit(2).unwrap());
330        assert!(!mask_a.bit(3).unwrap());
331
332        assert!(!mask_a.bit(8).unwrap());
333        assert!(!mask_a.bit(9).unwrap());
334        assert!(mask_a.bit(10).unwrap());
335        assert!(!mask_a.bit(11).unwrap());
336    }
337
338    #[test]
339    fn or() {
340        let mut mask_a = DiffMask::new(2);
341        mask_a.set_bit(4, true);
342        mask_a.set_bit(8, true);
343
344        let mut mask_b = DiffMask::new(2);
345        mask_b.set_bit(8, true);
346        mask_b.set_bit(12, true);
347
348        mask_a.or(&mask_b);
349
350        assert!(!mask_a.bit(0).unwrap());
351        assert!(mask_a.bit(4).unwrap());
352        assert!(mask_a.bit(8).unwrap());
353        assert!(mask_a.bit(12).unwrap());
354        assert!(!mask_a.bit(15).unwrap());
355    }
356
357    #[test]
358    fn clone() {
359        let mut mask_a = DiffMask::new(2);
360        mask_a.set_bit(2, true);
361        mask_a.set_bit(10, true);
362
363        let mask_b = mask_a.clone();
364
365        assert!(mask_b.bit(2).unwrap());
366        assert!(!mask_b.bit(4).unwrap());
367        assert!(!mask_b.bit(9).unwrap());
368        assert!(mask_b.bit(10).unwrap());
369    }
370}