Cycle buffer
This commit is contained in:
commit
995bb2042d
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
/.idea/
|
||||||
|
Cargo.lock
|
||||||
|
target/
|
||||||
13
Cargo.toml
Normal file
13
Cargo.toml
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
[package]
|
||||||
|
name = "bgtu-networks-2"
|
||||||
|
version = "0.0.0"
|
||||||
|
edition = "2024"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
eframe = { version = "0.33.3", default-features = false, features = ["default_fonts", "glow"] }
|
||||||
|
egui_extras = { version = "0.33.3" }
|
||||||
|
|
||||||
|
[dependencies.windows]
|
||||||
|
version = ">=0.41.0, <=0.62.2"
|
||||||
|
registry = "crates-io"
|
||||||
|
features = ["Win32_System_SystemInformation", "Win32_System_Memory"]
|
||||||
211
src/data/cycle_buffer.rs
Normal file
211
src/data/cycle_buffer.rs
Normal file
@ -0,0 +1,211 @@
|
|||||||
|
use std::mem::ManuallyDrop;
|
||||||
|
use std::ops::{Deref, DerefMut, IndexMut};
|
||||||
|
use std::ptr::NonNull;
|
||||||
|
|
||||||
|
pub(crate) struct CycledBuffer<T> {
|
||||||
|
pos: BufferState,
|
||||||
|
data: Vec<ManuallyDrop<T>>,
|
||||||
|
}
|
||||||
|
#[derive(Clone, Copy)]
|
||||||
|
enum BufferState {
|
||||||
|
Filling(usize),
|
||||||
|
Cycle(usize),
|
||||||
|
Empty,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> CycledBuffer<T> {
|
||||||
|
pub fn new(capacity: usize) -> Self {
|
||||||
|
return Self {
|
||||||
|
pos: if capacity > 0 {
|
||||||
|
BufferState::Filling(capacity)
|
||||||
|
} else {
|
||||||
|
BufferState::Empty
|
||||||
|
},
|
||||||
|
data: Vec::with_capacity(capacity),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn push(&mut self, value: T) {
|
||||||
|
match self.pos {
|
||||||
|
BufferState::Filling(mut left) => {
|
||||||
|
self.data.push(ManuallyDrop::new(value));
|
||||||
|
left -= 1;
|
||||||
|
if left == 0 {
|
||||||
|
self.pos = BufferState::Cycle(0);
|
||||||
|
} else {
|
||||||
|
self.pos = BufferState::Filling(left);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BufferState::Cycle(mut pos) => {
|
||||||
|
unsafe { ManuallyDrop::drop(&mut self.data[pos]) };
|
||||||
|
self.data[pos] = ManuallyDrop::new(value);
|
||||||
|
pos += 1;
|
||||||
|
if pos >= self.data.len() {
|
||||||
|
self.pos = BufferState::Cycle(0);
|
||||||
|
} else {
|
||||||
|
self.pos = BufferState::Cycle(pos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
BufferState::Empty => {
|
||||||
|
panic!("Can't add to empty buffer")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn _iter<C: Len, E, G: for<'x> Fn(&mut C, usize) -> E>(
|
||||||
|
state: BufferState,
|
||||||
|
collection: C,
|
||||||
|
getter: G,
|
||||||
|
) -> impl Iterator<Item = E> {
|
||||||
|
match state {
|
||||||
|
BufferState::Filling(_) => return CycledIterator::start(collection, 0, getter),
|
||||||
|
BufferState::Cycle(middle) => return CycledIterator::start(collection, middle, getter),
|
||||||
|
BufferState::Empty => return CycledIterator::ended(collection, getter),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter(&self) -> impl Iterator<Item = &T> {
|
||||||
|
return Self::_iter(self.pos, &self.data, |c, i| c[i].deref());
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
|
||||||
|
return Self::_iter(self.pos, &mut self.data, |c, i| unsafe {
|
||||||
|
NonNull::from_mut(c.index_mut(i).deref_mut()).as_mut()
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Drop for CycledBuffer<T> {
|
||||||
|
fn drop(&mut self) {
|
||||||
|
for e in self.data.iter_mut() {
|
||||||
|
unsafe {
|
||||||
|
ManuallyDrop::drop(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Len {
|
||||||
|
fn len(&self) -> usize;
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<T> Len for &Vec<T> {
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
return Vec::len(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
impl<T> Len for &mut Vec<T> {
|
||||||
|
fn len(&self) -> usize {
|
||||||
|
return Vec::len(self);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum IteratorState {
|
||||||
|
End { middle: usize },
|
||||||
|
Start { middle: usize },
|
||||||
|
Plain,
|
||||||
|
Done,
|
||||||
|
}
|
||||||
|
|
||||||
|
struct CycledIterator<C: Len, E, G: Fn(&mut C, usize) -> E> {
|
||||||
|
collection: C,
|
||||||
|
state: IteratorState,
|
||||||
|
pos: usize,
|
||||||
|
getter: G,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C: Len, E, G: Fn(&mut C, usize) -> E> CycledIterator<C, E, G> {
|
||||||
|
fn start(collection: C, middle: usize, getter: G) -> Self {
|
||||||
|
if middle > 0 {
|
||||||
|
return Self {
|
||||||
|
collection,
|
||||||
|
state: IteratorState::End { middle },
|
||||||
|
pos: middle,
|
||||||
|
getter,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
return Self {
|
||||||
|
collection,
|
||||||
|
state: IteratorState::Plain,
|
||||||
|
pos: 0,
|
||||||
|
getter,
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn ended(collection: C, getter: G) -> Self {
|
||||||
|
return Self {
|
||||||
|
collection,
|
||||||
|
state: IteratorState::Done,
|
||||||
|
pos: 0,
|
||||||
|
getter,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<C: Len, E, G: Fn(&mut C, usize) -> E> Iterator for CycledIterator<C, E, G> {
|
||||||
|
type Item = E;
|
||||||
|
|
||||||
|
fn next(&mut self) -> Option<Self::Item> {
|
||||||
|
match self.state {
|
||||||
|
IteratorState::End { middle } => {
|
||||||
|
let e = (self.getter)(&mut self.collection, self.pos);
|
||||||
|
self.pos += 1;
|
||||||
|
if self.pos >= self.collection.len() {
|
||||||
|
self.state = IteratorState::Start { middle };
|
||||||
|
self.pos = 0;
|
||||||
|
}
|
||||||
|
return Some(e);
|
||||||
|
}
|
||||||
|
IteratorState::Start { middle } => {
|
||||||
|
let e = (self.getter)(&mut self.collection, self.pos);
|
||||||
|
self.pos += 1;
|
||||||
|
if self.pos >= middle {
|
||||||
|
self.state = IteratorState::Done;
|
||||||
|
}
|
||||||
|
return Some(e);
|
||||||
|
}
|
||||||
|
IteratorState::Done => return None,
|
||||||
|
IteratorState::Plain => {
|
||||||
|
if self.pos < self.collection.len() {
|
||||||
|
let e = (self.getter)(&mut self.collection, self.pos);
|
||||||
|
self.pos += 1;
|
||||||
|
return Some(e);
|
||||||
|
} else {
|
||||||
|
self.state = IteratorState::Done;
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod _tests {
|
||||||
|
use crate::data::cycle_buffer::CycledBuffer;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test1() {
|
||||||
|
let mut b = CycledBuffer::new(3);
|
||||||
|
b.push(6);
|
||||||
|
b.push(9);
|
||||||
|
|
||||||
|
let mut it = b.iter();
|
||||||
|
assert_eq!(it.next(), Some(&6));
|
||||||
|
assert_eq!(it.next(), Some(&9));
|
||||||
|
assert_eq!(it.next(), None);
|
||||||
|
}
|
||||||
|
#[test]
|
||||||
|
fn test2() {
|
||||||
|
let mut b = CycledBuffer::new(2);
|
||||||
|
b.push(9);
|
||||||
|
b.push(5);
|
||||||
|
b.push(2);
|
||||||
|
|
||||||
|
let mut it = b.iter();
|
||||||
|
assert_eq!(it.next(), Some(&5));
|
||||||
|
assert_eq!(it.next(), Some(&2));
|
||||||
|
assert_eq!(it.next(), None);
|
||||||
|
}
|
||||||
|
}
|
||||||
1
src/data/mod.rs
Normal file
1
src/data/mod.rs
Normal file
@ -0,0 +1 @@
|
|||||||
|
mod cycle_buffer;
|
||||||
0
src/data2.rs
Normal file
0
src/data2.rs
Normal file
6
src/main.rs
Normal file
6
src/main.rs
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
mod data2;
|
||||||
|
mod data;
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
println!("Hello, world!");
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue
Block a user