#![allow(dead_code)]
#[allow(dead_code)]
#[derive(Debug, Clone)]
pub struct UidGen {
counter: u64,
namespace: u16,
recycled: Vec<u64>,
}
#[allow(dead_code)]
pub fn new_uid_gen(namespace: u16) -> UidGen {
UidGen {
counter: 1,
namespace,
recycled: Vec::new(),
}
}
#[allow(dead_code)]
pub fn ug_alloc(gen: &mut UidGen) -> u64 {
if let Some(uid) = gen.recycled.pop() {
return uid;
}
let uid = ((gen.namespace as u64) << 48) | gen.counter;
gen.counter += 1;
uid
}
#[allow(dead_code)]
pub fn ug_recycle(gen: &mut UidGen, uid: u64) {
if !gen.recycled.contains(&uid) {
gen.recycled.push(uid);
}
}
#[allow(dead_code)]
pub fn ug_allocated_count(gen: &UidGen) -> u64 {
gen.counter - 1
}
#[allow(dead_code)]
pub fn ug_recycled_count(gen: &UidGen) -> usize {
gen.recycled.len()
}
#[allow(dead_code)]
pub fn ug_namespace(uid: u64) -> u16 {
(uid >> 48) as u16
}
#[allow(dead_code)]
pub fn ug_local_id(uid: u64) -> u64 {
uid & 0x0000_FFFF_FFFF_FFFF
}
#[allow(dead_code)]
pub fn ug_reset(gen: &mut UidGen) {
gen.counter = 1;
gen.recycled.clear();
}
#[allow(dead_code)]
pub fn ug_peek_next(gen: &UidGen) -> u64 {
if let Some(&uid) = gen.recycled.last() {
return uid;
}
((gen.namespace as u64) << 48) | gen.counter
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_alloc_unique() {
let mut gen = new_uid_gen(1);
let a = ug_alloc(&mut gen);
let b = ug_alloc(&mut gen);
assert_ne!(a, b);
}
#[test]
fn test_namespace_encoded() {
let mut gen = new_uid_gen(7);
let uid = ug_alloc(&mut gen);
assert_eq!(ug_namespace(uid), 7);
}
#[test]
fn test_local_id_starts_at_one() {
let mut gen = new_uid_gen(0);
let uid = ug_alloc(&mut gen);
assert_eq!(ug_local_id(uid), 1);
}
#[test]
fn test_recycle_reuses() {
let mut gen = new_uid_gen(0);
let uid1 = ug_alloc(&mut gen);
ug_recycle(&mut gen, uid1);
let uid2 = ug_alloc(&mut gen);
assert_eq!(uid1, uid2);
}
#[test]
fn test_recycled_count() {
let mut gen = new_uid_gen(0);
let uid = ug_alloc(&mut gen);
ug_recycle(&mut gen, uid);
assert_eq!(ug_recycled_count(&gen), 1);
}
#[test]
fn test_allocated_count() {
let mut gen = new_uid_gen(0);
ug_alloc(&mut gen);
ug_alloc(&mut gen);
assert_eq!(ug_allocated_count(&gen), 2);
}
#[test]
fn test_reset() {
let mut gen = new_uid_gen(3);
ug_alloc(&mut gen);
ug_reset(&mut gen);
assert_eq!(ug_allocated_count(&gen), 0);
}
#[test]
fn test_peek_next() {
let gen = new_uid_gen(0);
let expected = 1u64;
assert_eq!(ug_peek_next(&gen), expected);
}
#[test]
fn test_no_duplicate_recycle() {
let mut gen = new_uid_gen(0);
let uid = ug_alloc(&mut gen);
ug_recycle(&mut gen, uid);
ug_recycle(&mut gen, uid);
assert_eq!(ug_recycled_count(&gen), 1);
}
}