rain_lang/
util.rs

1/*!
2Miscellaneous utilities
3*/
4
5use std::convert::Infallible;
6use std::hash::Hasher;
7
8/// A type may generically hold errors but is guaranteed never to do so in a particular instance.
9/// Stand-in for `#[feature(unwrap_infallible)]`
10pub trait AlwaysOk<T> {
11    /// Extract a value of a type from a generic error type statically guaranteed never
12    /// to hold an error.
13    fn aok(self) -> T;
14}
15
16impl<T, I> AlwaysOk<T> for Result<T, I> where I: Into<Infallible> {
17    #[inline] fn aok(self) -> T {
18        match self {
19            Ok(ok) => ok,
20            Err(err) => { let _err: Infallible = err.into(); match _err {} }
21        }
22    }
23}
24
25/// A hash function which simply returns the last eight bytes of input.
26#[derive(Debug, Copy, Clone, Default)]
27pub struct PassThroughHasher {
28    /// The starting value of the hasher
29    pub starting_value: u64
30}
31
32impl Hasher for PassThroughHasher {
33    #[inline(always)] fn finish(&self) -> u64 { self.starting_value }
34    #[inline(always)] fn write(&mut self, bytes: &[u8]) {
35        let mut new_value = [0; 8];
36        let mut i = 0;
37        for byte in bytes.iter().rev() {
38            if i >= 8 { break }
39            new_value[7 - i] = *byte;
40            i += 1;
41        }
42        let old_value = self.starting_value.to_ne_bytes();
43        for byte in old_value.iter().rev() {
44            if i >= 8 { break }
45            new_value[7 - i] = *byte;
46            i += 1;
47        }
48        self.starting_value = u64::from_ne_bytes(new_value);
49    }
50    #[inline(always)] fn write_u64(&mut self, value: u64) { self.starting_value = value }
51}
52
53#[cfg(test)]
54mod tests {
55    use super::*;
56    use rand_xoshiro::Xoshiro256StarStar;
57    use rand::SeedableRng;
58    use rand::Rng;
59
60    const RNG_SEED: u64 = 0xCAFEDECAF2832;
61
62    #[test]
63    fn pass_through_hasher_works() {
64        let mut hasher = PassThroughHasher::default();
65        assert_eq!(hasher.finish(), 0);
66        hasher.write(&[1, 2, 3, 4]);
67        assert_eq!(hasher.finish(), u64::from_ne_bytes([0, 0, 0, 0, 1, 2, 3, 4]));
68        hasher.write(&[5, 6, 7, 8]);
69        assert_eq!(hasher.finish(), u64::from_ne_bytes([1, 2, 3, 4, 5, 6, 7, 8]));
70
71        let mut rng = Xoshiro256StarStar::seed_from_u64(RNG_SEED);
72        for _ in 0..100 {
73            let val = rng.gen();
74            hasher.write_u64(val);
75            assert_eq!(hasher.finish(), val);
76            hasher.write(&val.to_ne_bytes());
77            assert_eq!(hasher.finish(), val);
78        }
79    }
80}