#[cfg(target_os = "macos")]
fn sanitize_os_name(name: &str) -> String {
const MAX_NAME: usize = 29;
if name.len() <= MAX_NAME {
return name.to_string();
}
let mut hash: u64 = 0xcbf29ce484222325;
for byte in name.as_bytes() {
hash ^= *byte as u64;
hash = hash.wrapping_mul(0x100000001b3);
}
const CHARS: &[u8] = b"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
let mut encoded = String::with_capacity(11);
let mut h = hash;
for _ in 0..11 {
encoded.push(CHARS[(h % 62) as usize] as char);
h /= 62;
}
let max_suffix = MAX_NAME - 14;
let suffix_len = max_suffix.min(name.len());
let suffix = &name[name.len() - suffix_len..];
let result = format!("sb-{encoded}{suffix}");
if result.len() > MAX_NAME {
format!("sb-{encoded}")
} else {
result
}
}
#[cfg(not(target_os = "macos"))]
fn sanitize_os_name(name: &str) -> String {
name.to_string()
}
#[derive(Debug, Clone)]
pub struct SlotBusConfig {
pub name: String,
pub prefix: String,
pub num_slots: usize,
pub region_size: usize,
pub wait_timeout_ms: u32,
pub instrumentation: bool,
}
impl Default for SlotBusConfig {
fn default() -> Self {
Self {
name: String::new(),
prefix: "slotbus".to_string(),
num_slots: 32,
region_size: 1_048_576, wait_timeout_ms: 5_000,
instrumentation: false,
}
}
}
impl SlotBusConfig {
pub fn builder() -> SlotBusConfigBuilder {
SlotBusConfigBuilder::default()
}
pub fn region_name(&self) -> String {
sanitize_os_name(&format!("{}-{}", self.prefix, self.name))
}
pub fn request_event_name(&self) -> String {
sanitize_os_name(&format!("{}-{}-req", self.prefix, self.name))
}
pub fn response_event_name(&self) -> String {
sanitize_os_name(&format!("{}-{}-rsp", self.prefix, self.name))
}
pub fn request_overflow_name(&self, slot: usize) -> String {
sanitize_os_name(&format!("{}-{}-req-{}", self.prefix, self.name, slot))
}
pub fn response_overflow_name(&self, slot: usize) -> String {
sanitize_os_name(&format!("{}-{}-rsp-{}", self.prefix, self.name, slot))
}
}
#[derive(Debug, Default)]
pub struct SlotBusConfigBuilder {
config: SlotBusConfig,
}
impl SlotBusConfigBuilder {
pub fn name(mut self, name: impl Into<String>) -> Self {
self.config.name = name.into();
self
}
pub fn prefix(mut self, prefix: impl Into<String>) -> Self {
self.config.prefix = prefix.into();
self
}
pub fn num_slots(mut self, n: usize) -> Self {
self.config.num_slots = n.clamp(1, 256);
self
}
pub fn region_size(mut self, size: usize) -> Self {
self.config.region_size = size;
self
}
pub fn wait_timeout_ms(mut self, ms: u32) -> Self {
self.config.wait_timeout_ms = ms;
self
}
pub fn instrumentation(mut self, enabled: bool) -> Self {
self.config.instrumentation = enabled;
self
}
pub fn build(self) -> SlotBusConfig {
assert!(!self.config.name.is_empty(), "slotbus: name is required");
self.config
}
}