1#[must_use]
14pub fn compute_seed(description: &str) -> u64 {
15 let mut hash: u64 = 0xcbf2_9ce4_8422_2325;
17 for byte in description.bytes() {
18 hash ^= u64::from(byte);
19 hash = hash.wrapping_mul(0x0000_0100_0000_01b3);
20 }
21 hash
22}
23
24#[must_use]
27pub fn resolve_seed(explicit: Option<u64>, description: &str) -> u64 {
28 explicit.unwrap_or_else(|| compute_seed(description))
29}
30
31#[cfg(test)]
32mod tests {
33 use super::*;
34
35 #[test]
36 fn test_compute_seed_deterministic() {
37 let a = compute_seed("hello:42:3.14");
38 let b = compute_seed("hello:42:3.14");
39 assert_eq!(a, b);
40 }
41
42 #[test]
43 fn test_compute_seed_known_value() {
44 let seed = compute_seed("test");
46 assert_eq!(seed, 0xf9e6_e6ef_197c_2b25);
47 }
48
49 #[test]
50 fn test_compute_seed_different_inputs() {
51 let a = compute_seed("hello");
52 let b = compute_seed("world");
53 assert_ne!(a, b);
54 }
55
56 #[test]
57 fn test_resolve_seed_explicit() {
58 let seed = resolve_seed(Some(42), "ignored");
59 assert_eq!(seed, 42);
60 }
61
62 #[test]
63 fn test_resolve_seed_derived() {
64 let seed = resolve_seed(None, "hello");
65 let expected = compute_seed("hello");
66 assert_eq!(seed, expected);
67 }
68}