///|
/// Stable FNV-1a style 32-bit hash over MoonBit UTF-16 code units.
pub fn stable_hash(text : String, seed? : UInt = 2166136261U) -> UInt {
let mut value = seed
for index = 0; index < text.length(); index = index + 1 {
let unit = text.unsafe_get(index).to_uint()
value = (value ^ (unit & 255U)) * 16777619U
value = (value ^ (unit >> 8)) * 16777619U
}
value
}
///|
/// Deterministically mixes a key, node identity, and namespace salt.
pub fn placement_score(key : String, node_id : String, salt : String) -> UInt {
stable_hash("\{salt.length()}:\{salt}|\{key.length()}:\{key}|\{node_id}")
}
///|
/// Creates a virtual-node position without ambiguous string concatenation.
pub fn virtual_position(node_id : String, replica : Int, seed : UInt) -> UInt {
stable_hash("\{node_id.length()}:\{node_id}#\{replica}", seed~)
}