aboutsummaryrefslogtreecommitdiff
path: root/embassy-extras/src/ring_buffer.rs
blob: f2b9f7359c21947a38d3537e79f2dd47a240f0d0 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
use crate::fmt::{assert, *};

pub struct RingBuffer<'a> {
    buf: &'a mut [u8],
    start: usize,
    end: usize,
    empty: bool,
}

impl<'a> RingBuffer<'a> {
    pub fn new(buf: &'a mut [u8]) -> Self {
        Self {
            buf,
            start: 0,
            end: 0,
            empty: true,
        }
    }

    pub fn push_buf(&mut self) -> &mut [u8] {
        if self.start == self.end && !self.empty {
            trace!("  ringbuf: push_buf empty");
            return &mut self.buf[..0];
        }

        let n = if self.start <= self.end {
            self.buf.len() - self.end
        } else {
            self.start - self.end
        };

        trace!("  ringbuf: push_buf {:?}..{:?}", self.end, self.end + n);
        &mut self.buf[self.end..self.end + n]
    }

    pub fn push(&mut self, n: usize) {
        trace!("  ringbuf: push {:?}", n);
        if n == 0 {
            return;
        }

        self.end = self.wrap(self.end + n);
        self.empty = false;
    }

    pub fn pop_buf(&mut self) -> &mut [u8] {
        if self.empty {
            trace!("  ringbuf: pop_buf empty");
            return &mut self.buf[..0];
        }

        let n = if self.end <= self.start {
            self.buf.len() - self.start
        } else {
            self.end - self.start
        };

        trace!("  ringbuf: pop_buf {:?}..{:?}", self.start, self.start + n);
        &mut self.buf[self.start..self.start + n]
    }

    pub fn pop(&mut self, n: usize) {
        trace!("  ringbuf: pop {:?}", n);
        if n == 0 {
            return;
        }

        self.start = self.wrap(self.start + n);
        self.empty = self.start == self.end;
    }

    fn wrap(&self, n: usize) -> usize {
        assert!(n <= self.buf.len());
        if n == self.buf.len() {
            0
        } else {
            n
        }
    }
}