1use std::collections::BTreeMap;
5use std::hash::{BuildHasher, Hasher};
6
7use crate::records::JsonValue;
8
9pub fn seeded(payload: &JsonValue) -> JsonValue {
13 let Some(mut fields) = seedable_fields(payload) else {
14 return payload.clone();
15 };
16 if let Some(seed) = fields.get("seed")
17 && *seed != JsonValue::Null
18 {
19 return JsonValue::Object(fields);
20 }
21 fields.insert("seed".to_owned(), JsonValue::Int(random_seed()));
22 JsonValue::Object(fields)
23}
24
25pub fn reseeded(params: &JsonValue) -> JsonValue {
28 let Some(mut fields) = seedable_fields(params) else {
29 return params.clone();
30 };
31 let previous = fields.get("seed").cloned();
32 let mut fresh = JsonValue::Int(random_seed());
33 while Some(&fresh) == previous.as_ref() {
34 fresh = JsonValue::Int(random_seed());
35 }
36 fields.insert("seed".to_owned(), fresh);
37 JsonValue::Object(fields)
38}
39
40fn seedable_fields(payload: &JsonValue) -> Option<BTreeMap<String, JsonValue>> {
41 match payload {
42 JsonValue::Object(fields) => Some(fields.clone()),
43 JsonValue::Null => Some(BTreeMap::new()),
44 _ => None,
45 }
46}
47
48fn random_seed() -> i64 {
51 let entropy = std::collections::hash_map::RandomState::new()
52 .build_hasher()
53 .finish();
54 (entropy % u32::MAX as u64) as i64
55}