simx00x 0.1.0

A no-std and no-alloc driver for SIM800L GSM modules (and probably similar modules)
Documentation
pub struct RingBuffer<T, const N: usize> {
    inner: [T; N],
    prod_idx: usize,
    cons_idx: usize,
}

impl<T, const N: usize> RingBuffer<T, N> {
    pub fn new(init: [T; N]) -> Self {
        assert!(N > 1);

        Self {
            inner: init,
            prod_idx: 0,
            cons_idx: 0,
        }
    }

    pub fn reset(&mut self) {
        self.prod_idx = 0;
        self.cons_idx = 0;
    }

    fn prod_avail(&self) -> bool {
        unsafe {
            match self.prod_idx < self.cons_idx {
                true => self.prod_idx.unchecked_add(1) != self.cons_idx,
                false => N.unchecked_sub(self.prod_idx).unchecked_add(self.cons_idx) != 1,
            }
        }
    }

    pub fn cons_avail(&self) -> bool {
        self.cons_idx != self.prod_idx
    }

    fn advance(target: &mut usize) {
        *target += 1;

        if *target == N {
            *target = 0;
        }
    }

    pub fn push(&mut self, item: T) -> bool {
        if self.prod_avail() {
            self.inner[self.prod_idx] = item;
            Self::advance(&mut self.prod_idx);
            true
        } else {
            false
        }
    }

    pub fn peek(&self) -> Option<&T> {
        self.cons_avail().then(|| &self.inner[self.cons_idx])
    }

    pub fn advance_cons(&mut self) {
        Self::advance(&mut self.cons_idx);
    }
}

#[cfg(test)]
mod tests {
    use crate::buffer::RingBuffer;

    const LEN: usize = 64;

    #[test]
    fn test2() {
        let mut buffer = RingBuffer::new([0; 2]);

        assert!(buffer.push(42));

        assert!(!buffer.prod_avail());
        assert!(buffer.cons_avail());

        assert_eq!(buffer.peek(), Some(&42));
        buffer.advance_cons();

        assert!(buffer.prod_avail());
        assert!(!buffer.cons_avail());
    }

    #[test]
    fn test_buffer() {
        let mut buffer = RingBuffer::new([0; LEN]);

        assert!(buffer.prod_avail());
        assert!(!buffer.cons_avail());

        assert!(buffer.push(1));

        assert!(buffer.prod_avail());
        assert!(buffer.cons_avail());

        assert!(buffer.peek().is_some());

        assert!(buffer.prod_avail());
        assert!(buffer.cons_avail());

        buffer.advance_cons();

        assert!(buffer.prod_avail());
        assert!(!buffer.cons_avail());

        for i in 0..LEN - 1 {
            assert!(buffer.push(i));
        }

        assert!(!buffer.prod_avail());
        assert!(buffer.cons_avail());

        for i in 0..LEN - 1 {
            assert_eq!(buffer.peek(), Some(&i));
            buffer.advance_cons();
        }

        assert!(buffer.prod_avail());
        assert!(!buffer.cons_avail());
    }

    #[test]
    fn test_wrap() {
        let mut buffer = RingBuffer::new([0; LEN]);

        for i in 0..LEN / 2 {
            assert!(buffer.push(i))
        }

        assert_eq!(buffer.prod_idx, LEN / 2);

        for _ in 0..LEN / 2 {
            buffer.advance_cons();
        }

        assert_eq!(buffer.prod_idx, buffer.cons_idx);

        for i in 0..LEN - 1 {
            assert!(buffer.push(i))
        }

        assert_eq!(buffer.prod_idx, LEN / 2 - 1);

        for _ in 0..LEN - 1 {
            buffer.advance_cons();
        }

        assert_eq!(buffer.prod_idx, buffer.cons_idx);
    }
}