use alloc::format;
use alloc::vec::Vec;
pub fn hash64(b: &[u8]) -> u64 {
let mut h: u64 = 0xCBF2_9CE4_8422_2325;
for &x in b {
h ^= x as u64;
h = h.wrapping_mul(0x0000_0100_0000_01B3);
}
let mut z = h;
z = (z ^ (z >> 30)).wrapping_mul(0xBF58_476D_1CE4_E5B9);
z = (z ^ (z >> 27)).wrapping_mul(0x94D0_49BB_1331_11EB);
z ^ (z >> 31)
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct Ring<M: Ord + Clone> {
tokens: Vec<(u64, M)>,
members: Vec<M>,
}
impl<M: Ord + Clone> Default for Ring<M> {
fn default() -> Self {
Ring::new()
}
}
impl<M: Ord + Clone> Ring<M> {
pub fn new() -> Ring<M> {
Ring { tokens: Vec::new(), members: Vec::new() }
}
pub fn add(&mut self, m: M, key: &str, vnodes: u32) {
self.remove(&m);
for i in 0..vnodes.max(1) {
self.tokens.push((hash64(format!("{}#{}", key, i).as_bytes()), m.clone()));
}
self.tokens.sort();
self.members.push(m);
self.members.sort();
}
pub fn remove(&mut self, m: &M) -> bool {
let before = self.members.len();
self.members.retain(|x| x != m);
self.tokens.retain(|t| &t.1 != m);
self.members.len() != before
}
pub fn members(&self) -> &[M] {
&self.members
}
pub fn tokens(&self) -> &[(u64, M)] {
&self.tokens
}
pub fn is_empty(&self) -> bool {
self.tokens.is_empty()
}
fn start(&self, h: u64) -> usize {
let i = self.tokens.partition_point(|t| t.0 < h);
if i == self.tokens.len() { 0 } else { i }
}
pub fn owner(&self, h: u64) -> Option<&M> {
if self.tokens.is_empty() {
return None;
}
Some(&self.tokens[self.start(h)].1)
}
pub fn preference(&self, h: u64, n: usize) -> Vec<M> {
self.preference_by(h, n, |_| true)
}
pub fn preference_by(&self, h: u64, n: usize, ok: impl Fn(&M) -> bool) -> Vec<M> {
let mut out: Vec<M> = Vec::new();
if self.tokens.is_empty() || n == 0 {
return out;
}
let s = self.start(h);
for k in 0..self.tokens.len() {
let m = &self.tokens[(s + k) % self.tokens.len()].1;
if !out.contains(m) && ok(m) {
out.push(m.clone());
if out.len() == n {
break;
}
}
}
out
}
pub fn shares(&self) -> Vec<(M, u32)> {
let n = self.tokens.len();
let mut out: Vec<(M, u32)> = self.members.iter().map(|m| (m.clone(), 0)).collect();
if n == 0 {
return out;
}
let mut arcs: Vec<u128> = alloc::vec![0; self.members.len()];
for i in 0..n {
let prev = if i == 0 { self.tokens[n - 1].0 } else { self.tokens[i - 1].0 };
let cur = self.tokens[i].0;
let len = if n == 1 { 1u128 << 64 } else { cur.wrapping_sub(prev) as u128 };
if let Ok(k) = self.members.binary_search(&self.tokens[i].1) {
arcs[k] += len;
}
}
for (k, a) in arcs.iter().enumerate() {
out[k].1 = ((a * 1_000_000) >> 64) as u32;
}
out
}
}