From 995bb2042df7769d28065aa5c6e69033802c5310 Mon Sep 17 00:00:00 2001 From: Andrew Golovashevich Date: Wed, 25 Feb 2026 19:55:30 +0300 Subject: [PATCH] Cycle buffer --- .gitignore | 3 + Cargo.toml | 13 +++ src/data/cycle_buffer.rs | 211 +++++++++++++++++++++++++++++++++++++++ src/data/mod.rs | 1 + src/data2.rs | 0 src/main.rs | 6 ++ 6 files changed, 234 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.toml create mode 100644 src/data/cycle_buffer.rs create mode 100644 src/data/mod.rs create mode 100644 src/data2.rs create mode 100644 src/main.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..b5488f8 --- /dev/null +++ b/.gitignore @@ -0,0 +1,3 @@ +/.idea/ +Cargo.lock +target/ \ No newline at end of file diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..e115a77 --- /dev/null +++ b/Cargo.toml @@ -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"] \ No newline at end of file diff --git a/src/data/cycle_buffer.rs b/src/data/cycle_buffer.rs new file mode 100644 index 0000000..6511d64 --- /dev/null +++ b/src/data/cycle_buffer.rs @@ -0,0 +1,211 @@ +use std::mem::ManuallyDrop; +use std::ops::{Deref, DerefMut, IndexMut}; +use std::ptr::NonNull; + +pub(crate) struct CycledBuffer { + pos: BufferState, + data: Vec>, +} +#[derive(Clone, Copy)] +enum BufferState { + Filling(usize), + Cycle(usize), + Empty, +} + +impl CycledBuffer { + 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 Fn(&mut C, usize) -> E>( + state: BufferState, + collection: C, + getter: G, + ) -> impl Iterator { + 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 { + return Self::_iter(self.pos, &self.data, |c, i| c[i].deref()); + } + + pub fn iter_mut(&mut self) -> impl Iterator { + return Self::_iter(self.pos, &mut self.data, |c, i| unsafe { + NonNull::from_mut(c.index_mut(i).deref_mut()).as_mut() + }); + } +} + +impl Drop for CycledBuffer { + fn drop(&mut self) { + for e in self.data.iter_mut() { + unsafe { + ManuallyDrop::drop(e); + } + } + } +} + +trait Len { + fn len(&self) -> usize; +} + +impl Len for &Vec { + fn len(&self) -> usize { + return Vec::len(self); + } +} +impl Len for &mut Vec { + fn len(&self) -> usize { + return Vec::len(self); + } +} + +enum IteratorState { + End { middle: usize }, + Start { middle: usize }, + Plain, + Done, +} + +struct CycledIterator E> { + collection: C, + state: IteratorState, + pos: usize, + getter: G, +} + +impl E> CycledIterator { + 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 E> Iterator for CycledIterator { + type Item = E; + + fn next(&mut self) -> Option { + 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); + } +} \ No newline at end of file diff --git a/src/data/mod.rs b/src/data/mod.rs new file mode 100644 index 0000000..ee250e4 --- /dev/null +++ b/src/data/mod.rs @@ -0,0 +1 @@ +mod cycle_buffer; \ No newline at end of file diff --git a/src/data2.rs b/src/data2.rs new file mode 100644 index 0000000..e69de29 diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..3566ed6 --- /dev/null +++ b/src/main.rs @@ -0,0 +1,6 @@ +mod data2; +mod data; + +fn main() { + println!("Hello, world!"); +}