Circular Buffer

1. Readme

循环缓冲区

循环缓冲区,或环形缓冲区是一种数据结构,它使用单个固定大小的缓冲区,就好像它是端到端连接一样。

循环缓冲区首先开始为空,并具有一些预定义的长度。例如,这是一个 7 元素的缓冲区:

[ ][ ][ ][ ][ ][ ][ ]

假设 1 被写入缓冲区的中间(其实精确的起始位置在循环缓冲区中无关紧要):

[ ][ ][ ][1][ ][ ][ ]

然后假设添加了另外两个元素 - 2 和 3 - 在 1 之后,附加:

[ ][ ][ ][1][2][3][ ]

如果从缓冲区中,删除了两个元素,则删除缓冲区内最旧的值。在这种情况下,删除的两个元素是 1 和 2,缓冲区只有 3:

[ ][ ][ ][ ][ ][3][ ]

如果缓冲区有 7 个元素,那么它就完全填满了:

[6][7][8][9][3][4][5]

当缓冲区已满时,将引发错误,警告客户端,进一步写入被阻止,直到插槽空闲为止。

当缓冲区已满时,客户端可以选择使用强制写入,覆盖最旧的数据。在这种情况下,添加了另外两个元素 - A 和 B - 它们会覆盖 3 和 4:

[6][7][8][9][A][B][5]

3 和 4 已被 A 和 B 取代,使得 5 现在是缓冲区中最旧的数据。最后,如果删除了两个元素,那么返回的是 5 和 6,和剩余的缓冲区:


[ ][7][8][9][A][B][ ]

因为有可用的空间,但如果客户端再次覆盖存储 C 和 D,那么先前存储 5 和 6 的空间将被使用,而不是 7 和 8 的位置。7 仍然是最旧的元素,缓冲区又是充分.

[D][7][8][9][A][B][C]

资源

维基百科http://en.wikipedia.org/wiki/Circular_Buffer

2. 开始你的表演

use std::marker::PhantomData;

pub struct CircularBuffer<T> {
   // This field is here to make the template compile and not to
   // complain about unused type parameter 'T'. Once you start
   // solving the exercise, delete this field and the 'std::marker::PhantomData'
   // import.
   field: PhantomData<T>,
}

#[derive(Debug, PartialEq)]
pub enum Error {
   EmptyBuffer,
   FullBuffer,
}

impl<T> CircularBuffer<T> {
   pub fn new(capacity: usize) -> Self {
       unimplemented!(
           "Construct a new CircularBuffer with the capacity to hold {}.",
           match capacity {
               1 => format!("1 element"),
               _ => format!("{} elements", capacity),
           }
       );
   }

   pub fn write(&mut self, _element: T) -> Result<(), Error> {
       unimplemented!("Write the passed element to the CircularBuffer or return FullBuffer error if CircularBuffer is full.");
   }

   pub fn read(&mut self) -> Result<T, Error> {
       unimplemented!("Read the oldest element from the CircularBuffer or return EmptyBuffer error if CircularBuffer is empty.");
   }

   pub fn clear(&mut self) {
       unimplemented!("Clear the CircularBuffer.");
   }

   pub fn overwrite(&mut self, _element: T) {
       unimplemented!("Write the passed element to the CircularBuffer, overwriting the existing elements if CircularBuffer is full.");
   }
}

3. 测试代码查看


# #![allow(unused_variables)]
#fn main() {
#[test]
fn error_on_read_empty_buffer() {
   let mut buffer = CircularBuffer::<char>::new(1);
   assert_eq!(Err(Error::EmptyBuffer), buffer.read());
}

#[test]
//#[ignore]
fn write_and_read_back_item() {
   let mut buffer = CircularBuffer::new(1);
   assert!(buffer.write('1').is_ok());
   assert_eq!(Ok('1'), buffer.read());
   assert_eq!(Err(Error::EmptyBuffer), buffer.read());
}

#[test]
//#[ignore]
fn write_and_read_back_multiple_items() {
   let mut buffer = CircularBuffer::new(2);
   assert!(buffer.write('1').is_ok());
   assert!(buffer.write('2').is_ok());
   assert_eq!(Ok('1'), buffer.read());
   assert_eq!(Ok('2'), buffer.read());
   assert_eq!(Err(Error::EmptyBuffer), buffer.read());
}

#[test]
//#[ignore]
fn alternate_write_and_read() {
   let mut buffer = CircularBuffer::new(2);
   assert!(buffer.write('1').is_ok());
   assert_eq!(Ok('1'), buffer.read());
   assert!(buffer.write('2').is_ok());
   assert_eq!(Ok('2'), buffer.read());
}

#[test]
//#[ignore]
fn clear_buffer() {
   let mut buffer = CircularBuffer::new(3);
   assert!(buffer.write('1').is_ok());
   assert!(buffer.write('2').is_ok());
   assert!(buffer.write('3').is_ok());
   buffer.clear();
   assert_eq!(Err(Error::EmptyBuffer), buffer.read());
   assert!(buffer.write('1').is_ok());
   assert!(buffer.write('2').is_ok());
   assert_eq!(Ok('1'), buffer.read());
   assert!(buffer.write('3').is_ok());
   assert_eq!(Ok('2'), buffer.read());
}

#[test]
//#[ignore]
fn full_buffer_error() {
   let mut buffer = CircularBuffer::new(2);
   assert!(buffer.write('1').is_ok());
   assert!(buffer.write('2').is_ok());
   assert_eq!(Err(Error::FullBuffer), buffer.write('3'));
}

#[test]
//#[ignore]
fn overwrite_item_in_non_full_buffer() {
   let mut buffer = CircularBuffer::new(2);
   assert!(buffer.write('1').is_ok());
   buffer.overwrite('2');
   assert_eq!(Ok('1'), buffer.read());
   assert_eq!(Ok('2'), buffer.read());
   assert_eq!(Err(Error::EmptyBuffer), buffer.read());
}

#[test]
//#[ignore]
fn overwrite_item_in_full_buffer() {
   let mut buffer = CircularBuffer::new(2);
   assert!(buffer.write('1').is_ok());
   assert!(buffer.write('2').is_ok());
   buffer.overwrite('A');
   assert_eq!(Ok('2'), buffer.read());
   assert_eq!(Ok('A'), buffer.read());
}

#[test]
//#[ignore]
fn integer_buffer() {
   let mut buffer = CircularBuffer::new(2);
   assert!(buffer.write(1).is_ok());
   assert!(buffer.write(2).is_ok());
   assert_eq!(Ok(1), buffer.read());
   assert!(buffer.write(-1).is_ok());
   assert_eq!(Ok(2), buffer.read());
   assert_eq!(Ok(-1), buffer.read());
   assert_eq!(Err(Error::EmptyBuffer), buffer.read());
}

#[test]
//#[ignore]
fn string_buffer() {
   let mut buffer = CircularBuffer::new(2);
   buffer.write("".to_string()).unwrap();
   buffer.write("Testing".to_string()).unwrap();
   assert_eq!(0, buffer.read().unwrap().len());
   assert_eq!(Ok("Testing".to_string()), buffer.read());
}

#}

4. 答案


# #![allow(unused_variables)]
#fn main() {
#[derive(Debug, PartialEq)]
pub enum Error {
   EmptyBuffer,
   FullBuffer,
}

pub struct CircularBuffer<T: Default + Clone> {
   buffer: Vec<T>,
   size: usize,
   start: usize,
   end: usize,
}

impl<T: Default + Clone> CircularBuffer<T> {
   // this circular buffer keeps an unallocated slot between the start and the end
   // when the buffer is full.
   pub fn new(size: usize) -> CircularBuffer<T> {
       CircularBuffer {
           buffer: vec![T::default(); size + 1],
           size: size + 1,
           start: 0,
           end: 0,
       }
   }

   pub fn read(&mut self) -> Result<T, Error> {
       if self.is_empty() {
           return Err(Error::EmptyBuffer);
       }

       let v = self.buffer.get(self.start).unwrap().clone();
       self.advance_start();
       Ok(v)
   }

   pub fn write(&mut self, byte: T) -> Result<(), Error> {
       if self.is_full() {
           return Err(Error::FullBuffer);
       }

       self.buffer[self.end] = byte;
       self.advance_end();
       Ok(())
   }

   pub fn overwrite(&mut self, byte: T) {
       if self.is_full() {
           self.advance_start();
       }

       self.buffer[self.end] = byte;
       self.advance_end();
   }

   pub fn clear(&mut self) {
       self.start = 0;
       self.end = 0;
   }

   pub fn is_empty(&self) -> bool {
       self.start == self.end
   }

   pub fn is_full(&self) -> bool {
       (self.end + 1) % self.size == self.start
   }

   fn advance_start(&mut self) {
       self.start = (self.start + 1) % self.size;
   }

   fn advance_end(&mut self) {
       self.end = (self.end + 1) % self.size;
   }
}

#}



填充/相关