137 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
			
		
		
	
	
			137 lines
		
	
	
		
			2.9 KiB
		
	
	
	
		
			Rust
		
	
	
	
	
	
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;
 | 
						|
    }
 | 
						|
 | 
						|
    pub fn is_full(&self) -> bool {
 | 
						|
        self.start == self.end && !self.empty
 | 
						|
    }
 | 
						|
 | 
						|
    pub fn is_empty(&self) -> bool {
 | 
						|
        self.empty
 | 
						|
    }
 | 
						|
 | 
						|
    pub fn clear(&mut self) {
 | 
						|
        self.start = 0;
 | 
						|
        self.end = 0;
 | 
						|
        self.empty = true;
 | 
						|
    }
 | 
						|
 | 
						|
    fn wrap(&self, n: usize) -> usize {
 | 
						|
        assert!(n <= self.buf.len());
 | 
						|
        if n == self.buf.len() {
 | 
						|
            0
 | 
						|
        } else {
 | 
						|
            n
 | 
						|
        }
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
#[cfg(test)]
 | 
						|
mod tests {
 | 
						|
    use super::*;
 | 
						|
 | 
						|
    #[test]
 | 
						|
    fn push_pop() {
 | 
						|
        let mut b = [0; 4];
 | 
						|
        let mut rb = RingBuffer::new(&mut b);
 | 
						|
        let buf = rb.push_buf();
 | 
						|
        assert_eq!(4, buf.len());
 | 
						|
        buf[0] = 1;
 | 
						|
        buf[1] = 2;
 | 
						|
        buf[2] = 3;
 | 
						|
        buf[3] = 4;
 | 
						|
        rb.push(4);
 | 
						|
 | 
						|
        let buf = rb.pop_buf();
 | 
						|
        assert_eq!(4, buf.len());
 | 
						|
        assert_eq!(1, buf[0]);
 | 
						|
        rb.pop(1);
 | 
						|
 | 
						|
        let buf = rb.pop_buf();
 | 
						|
        assert_eq!(3, buf.len());
 | 
						|
        assert_eq!(2, buf[0]);
 | 
						|
        rb.pop(1);
 | 
						|
 | 
						|
        let buf = rb.pop_buf();
 | 
						|
        assert_eq!(2, buf.len());
 | 
						|
        assert_eq!(3, buf[0]);
 | 
						|
        rb.pop(1);
 | 
						|
 | 
						|
        let buf = rb.pop_buf();
 | 
						|
        assert_eq!(1, buf.len());
 | 
						|
        assert_eq!(4, buf[0]);
 | 
						|
        rb.pop(1);
 | 
						|
 | 
						|
        let buf = rb.pop_buf();
 | 
						|
        assert_eq!(0, buf.len());
 | 
						|
 | 
						|
        let buf = rb.push_buf();
 | 
						|
        assert_eq!(4, buf.len());
 | 
						|
    }
 | 
						|
}
 |