use std::{
borrow::Cow,
sync::atomic::{AtomicU32, Ordering},
};
pub struct NameGenerator {
prefix: Cow<'static, str>,
counter: AtomicU32,
}
impl NameGenerator {
pub const fn new(prefix: &'static str) -> Self {
Self {
prefix: Cow::Borrowed(prefix), counter: AtomicU32::new(0),
}
}
pub fn with_prefix_slice(prefix: &str) -> Self {
Self {
prefix: Cow::Owned(prefix.to_owned()), counter: AtomicU32::new(0),
}
}
pub fn with_prefix_owned(prefix: String) -> Self {
Self {
prefix: Cow::Owned(prefix), counter: AtomicU32::new(0),
}
}
pub fn next_name(&self) -> String {
let prefix = &self.prefix;
let n = self.counter.fetch_add(1, Ordering::Relaxed);
format!("{prefix}-{n}")
}
pub fn custom_name(&self, addendum: &str) -> String {
let prefix = &self.prefix;
let n = self.counter.fetch_add(1, Ordering::Relaxed);
format!("{prefix}-{n}-{addendum}")
}
}
#[cfg(test)]
mod tests {
use crate::pipeline::util::{assert_send, assert_sync};
use super::NameGenerator;
#[test]
fn type_properties() {
assert_send::<NameGenerator>();
assert_sync::<NameGenerator>();
}
#[test]
fn unique_names() {
let g = NameGenerator::new("test");
assert_eq!(g.next_name(), "test-0");
assert_eq!(g.next_name(), "test-1");
assert_eq!(g.next_name(), "test-2");
assert_eq!(g.custom_name("wow"), "test-3-wow");
assert_eq!(g.custom_name("wow"), "test-4-wow");
assert_eq!(g.next_name(), "test-5");
}
}