use core::fmt;
#[cfg(not(feature = "std"))]
extern crate alloc;
#[derive(Debug, Clone, PartialEq, Eq)]
#[cfg_attr(feature = "serde", derive(serde::Serialize, serde::Deserialize))]
pub enum BufferCfg {
SpmcRing {
capacity: usize,
},
SingleLatest,
Mailbox,
}
impl BufferCfg {
pub fn validate(&self) -> Result<(), &'static str> {
match self {
BufferCfg::SpmcRing { capacity } => {
if *capacity == 0 {
return Err("SPMC ring capacity must be > 0");
}
Ok(())
}
BufferCfg::SingleLatest | BufferCfg::Mailbox => Ok(()),
}
}
pub fn name(&self) -> &'static str {
match self {
BufferCfg::SpmcRing { .. } => "spmc_ring",
BufferCfg::SingleLatest => "single_latest",
BufferCfg::Mailbox => "mailbox",
}
}
pub fn estimated_memory_bytes(&self, item_size: usize, consumer_count: usize) -> usize {
match self {
BufferCfg::SpmcRing { capacity } => {
let buffer_size = capacity * item_size;
let consumer_overhead = consumer_count * 64; buffer_size + consumer_overhead
}
BufferCfg::SingleLatest => {
let buffer_size = item_size + 8; let consumer_overhead = consumer_count * 16; buffer_size + consumer_overhead
}
BufferCfg::Mailbox => {
let buffer_size = item_size + 8; let notify_overhead = 32; let consumer_overhead = consumer_count * 16; buffer_size + notify_overhead + consumer_overhead
}
}
}
}
impl Default for BufferCfg {
fn default() -> Self {
BufferCfg::SpmcRing { capacity: 1024 }
}
}
impl fmt::Display for BufferCfg {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BufferCfg::SpmcRing { capacity } => write!(f, "SpmcRing(capacity={})", capacity),
BufferCfg::SingleLatest => write!(f, "SingleLatest"),
BufferCfg::Mailbox => write!(f, "Mailbox"),
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_buffer_cfg_validation() {
assert!(BufferCfg::SpmcRing { capacity: 1 }.validate().is_ok());
assert!(BufferCfg::SpmcRing { capacity: 1024 }.validate().is_ok());
assert!(BufferCfg::SingleLatest.validate().is_ok());
assert!(BufferCfg::Mailbox.validate().is_ok());
assert!(BufferCfg::SpmcRing { capacity: 0 }.validate().is_err());
}
#[test]
fn test_buffer_cfg_default() {
let cfg = BufferCfg::default();
assert_eq!(cfg, BufferCfg::SpmcRing { capacity: 1024 });
assert!(cfg.validate().is_ok());
}
#[test]
fn test_buffer_cfg_names() {
assert_eq!(BufferCfg::SpmcRing { capacity: 100 }.name(), "spmc_ring");
assert_eq!(BufferCfg::SingleLatest.name(), "single_latest");
assert_eq!(BufferCfg::Mailbox.name(), "mailbox");
}
#[test]
#[cfg(feature = "std")]
fn test_buffer_cfg_display() {
assert_eq!(
format!("{}", BufferCfg::SpmcRing { capacity: 512 }),
"SpmcRing(capacity=512)"
);
assert_eq!(format!("{}", BufferCfg::SingleLatest), "SingleLatest");
assert_eq!(format!("{}", BufferCfg::Mailbox), "Mailbox");
}
#[test]
fn test_estimated_memory() {
let cfg = BufferCfg::SpmcRing { capacity: 1024 };
let mem = cfg.estimated_memory_bytes(100, 3);
assert!(mem > 102_000 && mem < 103_000);
let cfg = BufferCfg::SingleLatest;
let mem = cfg.estimated_memory_bytes(100, 3);
assert!(mem > 100 && mem < 200);
let cfg = BufferCfg::Mailbox;
let mem = cfg.estimated_memory_bytes(100, 3);
assert!(mem > 140 && mem < 250);
}
#[test]
fn test_clone_and_equality() {
let cfg1 = BufferCfg::SpmcRing { capacity: 512 };
let cfg2 = cfg1.clone();
assert_eq!(cfg1, cfg2);
let cfg3 = BufferCfg::SingleLatest;
assert_ne!(cfg1, cfg3);
}
}