Skip to content

Commit

Permalink
Merge pull request exercism#52 from ekse/exercise-circular-buffer
Browse files Browse the repository at this point in the history
add exercise circular-buffer
  • Loading branch information
EduardoBautista committed Oct 10, 2015
2 parents b980f25 + e4990f1 commit 1f09e91
Show file tree
Hide file tree
Showing 5 changed files with 168 additions and 1 deletion.
4 changes: 4 additions & 0 deletions circular-buffer/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions circular-buffer/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[package]
name = "circular-buffer"
version = "0.0.0"
69 changes: 69 additions & 0 deletions circular-buffer/example.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
#[derive(Debug, PartialEq)]
pub enum Error {
EmptyBuffer,
FullBuffer,
}

pub struct CircularBuffer {
buffer: Vec<char>,
size: usize,
start: usize,
end: usize,
}

impl CircularBuffer {
// this circular buffer keeps an unallocated slot between the start and the end
// when the buffer is full.
pub fn new(size: usize) -> CircularBuffer {
let mut v = Vec::new();
v.reserve(size + 1);

// initialize the buffer
for _ in 0..(size + 1) {
v.push('0');
}

let buffer = CircularBuffer {
buffer: v,
size: size + 1,
start: 0,
end: 0
};

buffer
}

pub fn read(&mut self) -> Result<char, Error> {
if self.start == self.end {
return Err(Error::EmptyBuffer);
}

let v = *self.buffer.get(self.start).unwrap();
self.start = (self.start + 1) % self.size;

Ok(v)
}

pub fn write(&mut self, byte: char) -> Result<(), Error> {
if (self.end + 1) % self.size == self.start {
return Err(Error::FullBuffer);
} else {
self.buffer[self.end] = byte;
self.end = (self.end + 1) % self.size;
return Ok(());
}
}

pub fn overwrite(&mut self, byte: char) {
self.buffer[self.end] = byte;
self.end = (self.end + 1) % self.size;
if self.start == self.end {
self.start = (self.start + 1) % self.size;
}
}

pub fn clear(&mut self) {
self.start = 0;
self.end = 0;
}
}
90 changes: 90 additions & 0 deletions circular-buffer/tests/circular-buffer.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
extern crate circular_buffer;

#[allow(unused_must_use)]
mod tests {

use circular_buffer::{CircularBuffer, Error};

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

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

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

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

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

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

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

#[test]
#[ignore]
fn overwrite_item_in_full_buffer() {
let mut buffer = CircularBuffer::new(2);
buffer.write('1');
buffer.write('2');
buffer.overwrite('A');
assert_eq!('2', buffer.read().unwrap());
assert_eq!('A', buffer.read().unwrap());
}
}
3 changes: 2 additions & 1 deletion config.json
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@
"custom-set",
"tournament",
"rectangles",
"forth"
"forth",
"circular-buffer"
],
"deprecated": [

Expand Down

0 comments on commit 1f09e91

Please sign in to comment.