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