summaryrefslogtreecommitdiffstats
path: root/src/router/buffer.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/router/buffer.rs')
-rw-r--r--src/router/buffer.rs76
1 files changed, 76 insertions, 0 deletions
diff --git a/src/router/buffer.rs b/src/router/buffer.rs
new file mode 100644
index 0000000..3f348ea
--- /dev/null
+++ b/src/router/buffer.rs
@@ -0,0 +1,76 @@
+/* Ring buffer implementing the WireGuard queuing semantics:
+ *
+ * 1. A fixed sized buffer
+ * 2. Inserting into the buffer always succeeds, but might overwrite the oldest item
+ */
+
+const BUFFER_SIZE : usize = 1024;
+
+pub struct DiscardingRingBuffer<T> {
+ buf : [ Option<T> ; BUFFER_SIZE],
+ idx : usize,
+ next : usize
+}
+
+impl <T>DiscardingRingBuffer<T> where T: Copy {
+ pub fn new() -> Self {
+ DiscardingRingBuffer{
+ buf : [None; BUFFER_SIZE],
+ idx : 0,
+ next : 0
+ }
+ }
+
+ pub fn empty(&mut self) {
+ self.next = 0;
+ self.idx = 0;
+ for i in 1..BUFFER_SIZE {
+ self.buf[i] = None;
+ }
+ }
+
+ pub fn push(&mut self, val : T) {
+ // assign next slot (free / oldest)
+ self.buf[self.idx] = Some(val);
+ self.idx += 1;
+ self.idx %= BUFFER_SIZE;
+
+ // check for wrap-around
+ if self.idx == self.next {
+ self.next += 1;
+ self.next %= BUFFER_SIZE;
+ }
+ }
+
+ pub fn consume(&mut self) -> Option<T> {
+ match self.buf[self.next] {
+ None => None,
+ some => {
+ self.buf[self.next] = None;
+ self.next += 1;
+ self.next %= BUFFER_SIZE;
+ some
+ }
+ }
+ }
+
+ pub fn has_element(&self) -> bool {
+ match self.buf[self.next] {
+ None => true,
+ _ => false
+ }
+ }
+}
+
+
+proptest! {
+ #[test]
+ fn test_order(elems: Vec<usize>) {
+ let mut buf = DiscardingRingBuffer<usize>::new();
+
+ for e in &elems {
+ buf.push(e);
+ }
+
+ }
+} \ No newline at end of file