2022-09-21 19:42:59 +03:00
// Written by flopetautschnig (floscodes) (c) 2022
module datatypes
// RingBuffer - public struct that represents the ringbuffer
2022-11-26 19:23:26 +03:00
pub struct RingBuffer [ T ] {
2022-09-21 19:42:59 +03:00
mut :
reader int // index of the tail where data is going to be read
writer int // index of the head where data is going to be written
content [ ] T
}
// new_ringbuffer - creates an empty ringbuffer
2022-11-26 19:23:26 +03:00
pub fn new_ringbuffer [ T ] ( s int ) RingBuffer [ T ] {
return RingBuffer [ T ] {
2022-09-21 19:42:59 +03:00
content : [ ] T { len : s + 1 , cap : s + 1 }
} // increasing custom set size by one element in order to make ring flow possible, so that writer cannot equal reader before reader-index has been read.
}
// push - adds an element to the ringbuffer
2022-11-28 11:24:47 +03:00
pub fn ( mut rb RingBuffer [ T ] ) push ( element T ) ! {
2022-09-21 19:42:59 +03:00
if rb . is_full ( ) {
return error ( ' B u f f e r o v e r f l o w ' )
} else {
rb . content [ rb . writer ] = element
rb . move_writer ( )
}
}
// pop - returns the oldest element of the buffer
2022-11-28 11:24:47 +03:00
pub fn ( mut rb RingBuffer [ T ] ) pop ( ) ! T {
2022-09-21 19:42:59 +03:00
mut v := rb . content [ rb . reader ]
if rb . is_empty ( ) {
return error ( ' B u f f e r i s e m p t y ' )
} else {
rb . move_reader ( )
}
return v
}
// push_many - pushes an array to the buffer
2022-11-28 11:24:47 +03:00
pub fn ( mut rb RingBuffer [ T ] ) push_many ( elements [ ] T ) ! {
2022-09-21 19:42:59 +03:00
for v in elements {
rb . push ( v ) or { return err }
}
}
// pop_many - returns a given number(n) of elements of the buffer starting with the oldest one
2022-11-28 11:24:47 +03:00
pub fn ( mut rb RingBuffer [ T ] ) pop_many ( n u64 ) ! [ ] T {
2022-09-21 19:42:59 +03:00
mut elements := [ ] T { }
for _ in 0 .. n {
elements << rb . pop ( ) or { return err }
}
return elements
}
// is_empty - checks if the ringbuffer is empty
2022-11-26 19:23:26 +03:00
pub fn ( rb RingBuffer [ T ] ) is_empty ( ) bool {
2022-09-21 19:42:59 +03:00
return rb . reader == rb . writer // if reader equals writer it means that no value to read has been written before. It follows that the buffer is empty.
}
// is_full - checks if the ringbuffer is full
2022-11-26 19:23:26 +03:00
pub fn ( rb RingBuffer [ T ] ) is_full ( ) bool {
2022-09-21 19:42:59 +03:00
if rb . writer + 1 == rb . reader {
return true
} else if rb . writer == rb . content . len - 1 && rb . reader == 0 {
return true
} else {
return false
}
}
// capacity - returns the capacity of the ringbuffer
2022-11-26 19:23:26 +03:00
pub fn ( rb RingBuffer [ T ] ) capacity ( ) int {
2022-09-21 19:42:59 +03:00
return rb . content . cap - 1 // reduce by one because of the extra element explained in function `new_ringbuffer()`
}
// clear - emptys the ringbuffer and all pushed elements
2022-11-26 19:23:26 +03:00
pub fn ( mut rb RingBuffer [ T ] ) clear ( ) {
rb = RingBuffer [ T ] {
2022-09-21 19:42:59 +03:00
content : [ ] T { len : rb . content . len , cap : rb . content . cap }
}
}
// occupied - returns occupied capacity of the buffer.
2022-11-26 19:23:26 +03:00
pub fn ( rb RingBuffer [ T ] ) occupied ( ) int {
2022-09-21 19:42:59 +03:00
mut reader := rb . reader
mut v := 0
if rb . is_empty ( ) {
return v
}
for {
reader ++
if reader > rb . content . len - 1 {
reader = 0
}
v ++
if reader == rb . writer {
break
}
}
return v
}
// remaining - returns remaining capacity of the buffer
2022-11-26 19:23:26 +03:00
pub fn ( rb RingBuffer [ T ] ) remaining ( ) int {
2022-09-21 19:42:59 +03:00
return rb . capacity ( ) - rb . occupied ( )
}
// head an tail-pointer move methods
// these methods are not public, they are just an eneasement for handling the pointer-movement process.
2022-11-26 19:23:26 +03:00
fn ( mut rb RingBuffer [ T ] ) move_reader ( ) {
2022-09-21 19:42:59 +03:00
rb . reader ++
if rb . reader > rb . content . len - 1 {
rb . reader = 0
}
}
2022-11-26 19:23:26 +03:00
fn ( mut rb RingBuffer [ T ] ) move_writer ( ) {
2022-09-21 19:42:59 +03:00
rb . writer ++
if rb . writer > rb . content . len - 1 {
rb . writer = 0
}
}