rscache/util/
isaac_rand.rs

1const GOLDEN_RATIO: u32 = 0x9e3779b9;
2const LOG_SIZE: u32 = 8;
3const SIZE: usize = 1 << LOG_SIZE;
4const MASK: u32 = (SIZE as u32 - 1) << 2;
5
6/// Default Isaac random implementation
7///
8/// Can be used to encode and decode game packet id's.
9///
10/// Note: The client will only send one set of keys, the decoder keys.
11/// To get the encoder keys, simply add 50 to every decoder key.
12/// ```
13/// # let xtea_keys: Vec<u32> = vec![0; 4];
14/// let mut isaac_decoder_keys = Vec::with_capacity(4);
15/// let mut isaac_encoder_keys = Vec::with_capacity(4);
16/// 
17/// for key in xtea_keys {
18///     isaac_decoder_keys.push(key);
19///     isaac_encoder_keys.push(key + 50);
20/// }
21/// ```
22///
23/// # Examples
24///
25/// ```
26/// # use rscache::util::IsaacRand;
27/// # struct ExamplePacket { pub id: u32 }
28/// # fn main() -> std::io::Result<()> {
29/// # let encoder_keys = Vec::new();
30/// # let decoder_keys = Vec::new();
31/// # let packet_buffer = &[0];
32/// # let packet = ExamplePacket { id: 0 };
33/// let mut packet_id_encoder = IsaacRand::new(&encoder_keys);
34/// let mut packet_id_decoder = IsaacRand::new(&decoder_keys);
35///
36/// // decoding game packet id that was sent by the client.
37/// let packet_id =
38///     (packet_buffer[0] as u32).overflowing_sub(packet_id_decoder.next().unwrap());
39///
40/// // encoding packet id that will be sent to the client.
41/// let packet_id = packet.id + packet_id_encoder.next().unwrap();
42/// # Ok(())
43/// # }
44/// ```
45#[derive(Clone, Eq, PartialEq, Ord, PartialOrd, Hash, Debug, Default)]
46pub struct IsaacRand {
47    a: u32,
48    b: u32,
49    c: u32,
50    count: usize,
51    mem: Vec<u32>,
52    rsl: Vec<u32>,
53}
54
55impl IsaacRand {
56    /// Initializes the randomizer with the given seed.
57    pub fn new(seed: &[u32]) -> Self {
58        let mem = vec![0; SIZE];
59        let mut rsl = vec![0; SIZE];
60        rsl[..seed.len()].clone_from_slice(seed);
61
62        let mut isaac = Self {
63            a: 0,
64            b: 0,
65            c: 0,
66            count: 0,
67            mem,
68            rsl,
69        };
70        isaac.init();
71        isaac
72    }
73    fn init(&mut self) {
74        let mut h = GOLDEN_RATIO;
75        let mut g = h;
76        let mut f = g;
77        let mut e = f;
78        let mut d = e;
79        let mut c = d;
80        let mut b = c;
81        let mut a = b;
82
83        let mut i = 0;
84        while i < 4 {
85            a ^= b << 11;
86            d = d.wrapping_add(a);
87            b = b.wrapping_add(c);
88            b ^= c >> 2;
89            e = e.wrapping_add(b);
90            c = c.wrapping_add(d);
91            c ^= d << 8;
92            f = f.wrapping_add(c);
93            d = d.wrapping_add(e);
94            d ^= e >> 16;
95            g = g.wrapping_add(d);
96            e = e.wrapping_add(f);
97            e ^= f << 10;
98            h = h.wrapping_add(e);
99            f = f.wrapping_add(g);
100            f ^= g >> 4;
101            a = a.wrapping_add(f);
102            g = g.wrapping_add(h);
103            g ^= h << 8;
104            b = b.wrapping_add(g);
105            h = h.wrapping_add(a);
106            h ^= a >> 9;
107            c = c.wrapping_add(h);
108            a = a.wrapping_add(b);
109            i += 1;
110        }
111
112        i = 0;
113        while i < SIZE {
114            a = a.wrapping_add(self.rsl[i]);
115            b = b.wrapping_add(self.rsl[i + 1]);
116            c = c.wrapping_add(self.rsl[i + 2]);
117            d = d.wrapping_add(self.rsl[i + 3]);
118            e = e.wrapping_add(self.rsl[i + 4]);
119            f = f.wrapping_add(self.rsl[i + 5]);
120            g = g.wrapping_add(self.rsl[i + 6]);
121            h = h.wrapping_add(self.rsl[i + 7]);
122
123            a ^= b << 11;
124            d = d.wrapping_add(a);
125            b = b.wrapping_add(c);
126            b ^= c >> 2;
127            e = e.wrapping_add(b);
128            c = c.wrapping_add(d);
129            c ^= d << 8;
130            f = f.wrapping_add(c);
131            d = d.wrapping_add(e);
132            d ^= e >> 16;
133            g = g.wrapping_add(d);
134            e = e.wrapping_add(f);
135            e ^= f << 10;
136            h = h.wrapping_add(e);
137            f = f.wrapping_add(g);
138            f ^= g >> 4;
139            a = a.wrapping_add(f);
140            g = g.wrapping_add(h);
141            g ^= h << 8;
142            b = b.wrapping_add(g);
143            h = h.wrapping_add(a);
144            h ^= a >> 9;
145            c = c.wrapping_add(h);
146            a = a.wrapping_add(b);
147            self.mem[i] = a;
148            self.mem[i + 1] = b;
149            self.mem[i + 2] = c;
150            self.mem[i + 3] = d;
151            self.mem[i + 4] = e;
152            self.mem[i + 5] = f;
153            self.mem[i + 6] = g;
154            self.mem[i + 7] = h;
155            i += 8;
156        }
157
158        i = 0;
159        while i < SIZE {
160            a = a.wrapping_add(self.mem[i]);
161            b = b.wrapping_add(self.mem[i + 1]);
162            c = c.wrapping_add(self.mem[i + 2]);
163            d = d.wrapping_add(self.mem[i + 3]);
164            e = e.wrapping_add(self.mem[i + 4]);
165            f = f.wrapping_add(self.mem[i + 5]);
166            g = g.wrapping_add(self.mem[i + 6]);
167            h = h.wrapping_add(self.mem[i + 7]);
168            a ^= b << 11;
169            d = d.wrapping_add(a);
170            b = b.wrapping_add(c);
171            b ^= c >> 2;
172            e = e.wrapping_add(b);
173            c = c.wrapping_add(d);
174            c ^= d << 8;
175            f = f.wrapping_add(c);
176            d = d.wrapping_add(e);
177            d ^= e >> 16;
178            g = g.wrapping_add(d);
179            e = e.wrapping_add(f);
180            e ^= f << 10;
181            h = h.wrapping_add(e);
182            f = f.wrapping_add(g);
183            f ^= g >> 4;
184            a = a.wrapping_add(f);
185            g = g.wrapping_add(h);
186            g ^= h << 8;
187            b = b.wrapping_add(g);
188            h = h.wrapping_add(a);
189            h ^= a >> 9;
190            c = c.wrapping_add(h);
191            a = a.wrapping_add(b);
192            self.mem[i] = a;
193            self.mem[i + 1] = b;
194            self.mem[i + 2] = c;
195            self.mem[i + 3] = d;
196            self.mem[i + 4] = e;
197            self.mem[i + 5] = f;
198            self.mem[i + 6] = g;
199            self.mem[i + 7] = h;
200            i += 8;
201        }
202
203        self.isaac();
204        self.count = SIZE;
205    }
206
207    fn isaac(&mut self) {
208        let mut i = 0;
209        let mut j = SIZE / 2;
210        let mut x;
211        let mut y;
212
213        self.c += 1;
214        self.b += self.c;
215        while i < SIZE / 2 {
216            x = self.mem[i];
217            self.a = self.a ^ (self.a << 13);
218            self.a = self.a.wrapping_add(self.mem[j]);
219            j += 1;
220            y = self.mem[((x & MASK) >> 2) as usize]
221                .wrapping_add(self.a)
222                .wrapping_add(self.b);
223            self.mem[i] = y;
224            self.b = self.mem[(((y >> LOG_SIZE) & MASK) >> 2) as usize].wrapping_add(x);
225            self.rsl[i] = self.b;
226            i += 1;
227
228            x = self.mem[i];
229            self.a = self.a ^ self.a >> 6;
230            self.a = self.a.wrapping_add(self.mem[j]);
231            j += 1;
232            y = self.mem[((x & MASK) >> 2) as usize]
233                .wrapping_add(self.a)
234                .wrapping_add(self.b);
235            self.mem[i] = y;
236            self.b = self.mem[(((y >> LOG_SIZE) & MASK) >> 2) as usize].wrapping_add(x);
237            self.rsl[i] = self.b;
238            i += 1;
239
240            x = self.mem[i];
241            self.a = self.a ^ (self.a << 2);
242            self.a = self.a.wrapping_add(self.mem[j]);
243            j += 1;
244            y = self.mem[((x & MASK) >> 2) as usize]
245                .wrapping_add(self.a)
246                .wrapping_add(self.b);
247            self.mem[i] = y;
248            self.b = self.mem[(((y >> LOG_SIZE) & MASK) >> 2) as usize].wrapping_add(x);
249            self.rsl[i] = self.b;
250            i += 1;
251
252            x = self.mem[i];
253            self.a = self.a ^ self.a >> 16;
254            self.a = self.a.wrapping_add(self.mem[j]);
255            j += 1;
256            y = self.mem[((x & MASK) >> 2) as usize]
257                .wrapping_add(self.a)
258                .wrapping_add(self.b);
259            self.mem[i] = y;
260            self.b = self.mem[(((y >> LOG_SIZE) & MASK) >> 2) as usize].wrapping_add(x);
261            self.rsl[i] = self.b;
262            i += 1;
263        }
264
265        j = 0;
266        while j < SIZE / 2 {
267            x = self.mem[i];
268            self.a = self.a ^ (self.a << 13);
269            self.a = self.a.wrapping_add(self.mem[j]);
270            j += 1;
271            y = self.mem[((x & MASK) >> 2) as usize]
272                .wrapping_add(self.a)
273                .wrapping_add(self.b);
274            self.mem[i] = y;
275            self.b = self.mem[(((y >> LOG_SIZE) & MASK) >> 2) as usize].wrapping_add(x);
276            self.rsl[i] = self.b;
277            i += 1;
278
279            x = self.mem[i];
280            self.a = self.a ^ self.a >> 6;
281            self.a = self.a.wrapping_add(self.mem[j]);
282            j += 1;
283            y = self.mem[((x & MASK) >> 2) as usize]
284                .wrapping_add(self.a)
285                .wrapping_add(self.b);
286            self.mem[i] = y;
287            self.b = self.mem[(((y >> LOG_SIZE) & MASK) >> 2) as usize].wrapping_add(x);
288            self.rsl[i] = self.b;
289            i += 1;
290
291            x = self.mem[i];
292            self.a = self.a ^ (self.a << 2);
293            self.a = self.a.wrapping_add(self.mem[j]);
294            j += 1;
295            y = self.mem[((x & MASK) >> 2) as usize]
296                .wrapping_add(self.a)
297                .wrapping_add(self.b);
298            self.mem[i] = y;
299            self.b = self.mem[(((y >> LOG_SIZE) & MASK) >> 2) as usize].wrapping_add(x);
300            self.rsl[i] = self.b;
301            i += 1;
302
303            x = self.mem[i];
304            self.a = self.a ^ self.a >> 16;
305            self.a = self.a.wrapping_add(self.mem[j]);
306            j += 1;
307            y = self.mem[((x & MASK) >> 2) as usize]
308                .wrapping_add(self.a)
309                .wrapping_add(self.b);
310            self.mem[i] = y;
311            self.b = self.mem[(((y >> LOG_SIZE) & MASK) >> 2) as usize].wrapping_add(x);
312            self.rsl[i] = self.b;
313            i += 1;
314        }
315    }
316}
317
318impl Iterator for IsaacRand {
319    type Item = u32;
320
321    fn next(&mut self) -> Option<Self::Item> {
322        if self.count == 0 {
323            self.isaac();
324            self.count = SIZE;
325        }
326        self.count -= 1;
327
328        Some(self.rsl[self.count])
329    }
330}