Skip to content

Commit 1f09e91

Browse files
Merge pull request #52 from ekse/exercise-circular-buffer
add exercise circular-buffer
2 parents b980f25 + e4990f1 commit 1f09e91

File tree

5 files changed

+168
-1
lines changed

5 files changed

+168
-1
lines changed

circular-buffer/Cargo.lock

Lines changed: 4 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

circular-buffer/Cargo.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[package]
2+
name = "circular-buffer"
3+
version = "0.0.0"

circular-buffer/example.rs

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
#[derive(Debug, PartialEq)]
2+
pub enum Error {
3+
EmptyBuffer,
4+
FullBuffer,
5+
}
6+
7+
pub struct CircularBuffer {
8+
buffer: Vec<char>,
9+
size: usize,
10+
start: usize,
11+
end: usize,
12+
}
13+
14+
impl CircularBuffer {
15+
// this circular buffer keeps an unallocated slot between the start and the end
16+
// when the buffer is full.
17+
pub fn new(size: usize) -> CircularBuffer {
18+
let mut v = Vec::new();
19+
v.reserve(size + 1);
20+
21+
// initialize the buffer
22+
for _ in 0..(size + 1) {
23+
v.push('0');
24+
}
25+
26+
let buffer = CircularBuffer {
27+
buffer: v,
28+
size: size + 1,
29+
start: 0,
30+
end: 0
31+
};
32+
33+
buffer
34+
}
35+
36+
pub fn read(&mut self) -> Result<char, Error> {
37+
if self.start == self.end {
38+
return Err(Error::EmptyBuffer);
39+
}
40+
41+
let v = *self.buffer.get(self.start).unwrap();
42+
self.start = (self.start + 1) % self.size;
43+
44+
Ok(v)
45+
}
46+
47+
pub fn write(&mut self, byte: char) -> Result<(), Error> {
48+
if (self.end + 1) % self.size == self.start {
49+
return Err(Error::FullBuffer);
50+
} else {
51+
self.buffer[self.end] = byte;
52+
self.end = (self.end + 1) % self.size;
53+
return Ok(());
54+
}
55+
}
56+
57+
pub fn overwrite(&mut self, byte: char) {
58+
self.buffer[self.end] = byte;
59+
self.end = (self.end + 1) % self.size;
60+
if self.start == self.end {
61+
self.start = (self.start + 1) % self.size;
62+
}
63+
}
64+
65+
pub fn clear(&mut self) {
66+
self.start = 0;
67+
self.end = 0;
68+
}
69+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
extern crate circular_buffer;
2+
3+
#[allow(unused_must_use)]
4+
mod tests {
5+
6+
use circular_buffer::{CircularBuffer, Error};
7+
8+
#[test]
9+
fn error_on_read_empty_buffer() {
10+
let mut buffer = CircularBuffer::new(1);
11+
assert_eq!(Err(Error::EmptyBuffer), buffer.read());
12+
}
13+
14+
#[test]
15+
#[ignore]
16+
fn write_and_read_back_item() {
17+
let mut buffer = CircularBuffer::new(1);
18+
buffer.write('1');
19+
assert_eq!('1', buffer.read().unwrap());
20+
assert_eq!(Err(Error::EmptyBuffer), buffer.read());
21+
}
22+
23+
#[test]
24+
#[ignore]
25+
fn write_and_read_back_multiple_items() {
26+
let mut buffer = CircularBuffer::new(2);
27+
buffer.write('1');
28+
buffer.write('2');
29+
assert_eq!('1', buffer.read().unwrap());
30+
assert_eq!('2', buffer.read().unwrap());
31+
assert_eq!(Err(Error::EmptyBuffer), buffer.read());
32+
}
33+
34+
#[test]
35+
#[ignore]
36+
fn alternate_write_and_read() {
37+
let mut buffer = CircularBuffer::new(2);
38+
buffer.write('1');
39+
assert_eq!('1', buffer.read().unwrap());
40+
buffer.write('2');
41+
assert_eq!('2', buffer.read().unwrap());
42+
}
43+
44+
#[test]
45+
#[ignore]
46+
fn clear_buffer() {
47+
let mut buffer = CircularBuffer::new(3);
48+
buffer.write('1');
49+
buffer.write('2');
50+
buffer.write('3');
51+
buffer.clear();
52+
assert_eq!(Err(Error::EmptyBuffer), buffer.read());
53+
buffer.write('1');
54+
buffer.write('2');
55+
assert_eq!('1', buffer.read().unwrap());
56+
buffer.write('3');
57+
assert_eq!('2', buffer.read().unwrap());
58+
}
59+
60+
#[test]
61+
#[ignore]
62+
fn full_buffer_error() {
63+
let mut buffer = CircularBuffer::new(2);
64+
buffer.write('1');
65+
buffer.write('2');
66+
assert_eq!(Err(Error::FullBuffer), buffer.write('3'));
67+
}
68+
69+
#[test]
70+
#[ignore]
71+
fn overwrite_item_in_non_full_buffer() {
72+
let mut buffer = CircularBuffer::new(2);
73+
buffer.write('1');
74+
buffer.overwrite('2');
75+
assert_eq!('1', buffer.read().unwrap());
76+
assert_eq!('2', buffer.read().unwrap());
77+
assert_eq!(Err(Error::EmptyBuffer), buffer.read());
78+
}
79+
80+
#[test]
81+
#[ignore]
82+
fn overwrite_item_in_full_buffer() {
83+
let mut buffer = CircularBuffer::new(2);
84+
buffer.write('1');
85+
buffer.write('2');
86+
buffer.overwrite('A');
87+
assert_eq!('2', buffer.read().unwrap());
88+
assert_eq!('A', buffer.read().unwrap());
89+
}
90+
}

config.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@
2727
"custom-set",
2828
"tournament",
2929
"rectangles",
30-
"forth"
30+
"forth",
31+
"circular-buffer"
3132
],
3233
"deprecated": [
3334

0 commit comments

Comments
 (0)