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#[must_use]
36pub fn derive_seed(parent: u64, namespace: &str) -> u64 {
37 compute_seed(&format!("{parent:016x}:{namespace}"))
38}
39
40#[cfg(test)]
41mod tests {
42 use super::*;
43
44 #[test]
45 fn test_compute_seed_deterministic() {
46 let a = compute_seed("hello:42:3.14");
47 let b = compute_seed("hello:42:3.14");
48 assert_eq!(a, b);
49 }
50
51 #[test]
52 fn test_compute_seed_known_value() {
53 let seed = compute_seed("test");
55 assert_eq!(seed, 0xf9e6_e6ef_197c_2b25);
56 }
57
58 #[test]
59 fn test_compute_seed_different_inputs() {
60 let a = compute_seed("hello");
61 let b = compute_seed("world");
62 assert_ne!(a, b);
63 }
64
65 #[test]
66 fn test_resolve_seed_explicit() {
67 let seed = resolve_seed(Some(42), "ignored");
68 assert_eq!(seed, 42);
69 }
70
71 #[test]
72 fn test_resolve_seed_derived() {
73 let seed = resolve_seed(None, "hello");
74 let expected = compute_seed("hello");
75 assert_eq!(seed, expected);
76 }
77
78 #[test]
79 fn test_derive_seed_deterministic() {
80 let a = derive_seed(42, "chr1");
81 let b = derive_seed(42, "chr1");
82 assert_eq!(a, b);
83 }
84
85 #[test]
86 fn test_derive_seed_varies_with_namespace() {
87 let a = derive_seed(42, "chr1");
88 let b = derive_seed(42, "chr2");
89 assert_ne!(a, b);
90 }
91
92 #[test]
93 fn test_derive_seed_varies_with_parent() {
94 let a = derive_seed(1, "chr1");
95 let b = derive_seed(2, "chr1");
96 assert_ne!(a, b);
97 }
98}