Cycle buffer

This commit is contained in:
Andrew Golovashevich 2026-02-25 19:55:30 +03:00
commit 995bb2042d
6 changed files with 234 additions and 0 deletions

3
.gitignore vendored Normal file
View File

@ -0,0 +1,3 @@
/.idea/
Cargo.lock
target/

13
Cargo.toml Normal file
View 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
View 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
View File

@ -0,0 +1 @@
mod cycle_buffer;

0
src/data2.rs Normal file
View File

6
src/main.rs Normal file
View File

@ -0,0 +1,6 @@
mod data2;
mod data;
fn main() {
println!("Hello, world!");
}