ztopic 0.3.18

A topic-based pub/sub library for Rust
Documentation
use std::{cmp::Ordering, fmt::Debug};

use crate::Storage;

#[derive(Debug)]
pub struct Broadcast<V> {
    buffer: Vec<Option<V>>,
    capacity: usize,
    cursor: usize,
}

impl<V> Clone for Broadcast<V> {
    fn clone(&self) -> Self {
        Self {
            buffer: (0..self.capacity).map(|_| None).collect(),
            capacity: self.capacity,
            cursor: self.cursor,
        }
    }
}

impl<V> Broadcast<V> {
    pub fn new(capacity: usize) -> Self {
        assert!(capacity > 0);
        Self {
            buffer: (0..capacity).map(|_| None).collect(),
            capacity,
            cursor: 0,
        }
    }

    fn next_cursor(&self, cursor: usize) -> usize {
        let cursor = cursor + 1;
        if cursor < self.capacity {
            cursor
        } else {
            0
        }
    }
}

impl<V> Storage<V> for Broadcast<V> {
    fn insert(&mut self, value: V) {
        let cursor = self.cursor;
        self.buffer[cursor] = Some(value);
        self.cursor = self.next_cursor(cursor);
    }

    fn get_item(&self, cursor: usize) -> Option<(&V, usize)> {
        if cursor == self.cursor {
            return None;
        }
        self.buffer[cursor].as_ref().map(|v| (v, self.next_cursor(cursor)))
    }

    fn get_prev_cursor(&self) -> usize {
        let cursor = self.cursor;
        let prev_cursor = if cursor == 0 { self.capacity - 1 } else { cursor - 1 };
        match self.buffer.get(prev_cursor) {
            Some(_) => prev_cursor,
            None => cursor,
        }
    }

    fn size_hint(&self, cursor: usize) -> usize {
        match self.cursor.cmp(&cursor) {
            Ordering::Less => self.capacity - cursor + self.cursor,
            Ordering::Equal => 0,
            Ordering::Greater => self.cursor - cursor,
        }
    }
}