Reversed iterator in cycled buffer

This commit is contained in:
Andrew Golovashevich 2026-03-10 19:38:42 +03:00
parent a61c5332a0
commit ff64f16bde
2 changed files with 53 additions and 46 deletions

View File

@ -4,12 +4,12 @@ use std::ptr::NonNull;
pub(crate) struct CycledBuffer<T> {
pos: BufferState,
data: Vec<ManuallyDrop<T>>,
data: Vec<T>,
}
#[derive(Clone, Copy)]
enum BufferState {
Filling(usize),
Cycle(usize),
Filling { unfilled_count: usize },
Cycle { next_write_pos: usize },
Empty,
}
@ -17,7 +17,9 @@ impl<T> CycledBuffer<T> {
pub fn new(capacity: usize) -> Self {
return Self {
pos: if capacity > 0 {
BufferState::Filling(capacity)
BufferState::Filling {
unfilled_count: capacity,
}
} else {
BufferState::Empty
},
@ -27,23 +29,22 @@ impl<T> CycledBuffer<T> {
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);
BufferState::Filling { mut unfilled_count } => {
self.data.push(value);
unfilled_count -= 1;
if unfilled_count == 0 {
self.pos = BufferState::Cycle { next_write_pos: 0 };
} else {
self.pos = BufferState::Filling(left);
self.pos = BufferState::Filling { unfilled_count };
}
}
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);
BufferState::Cycle { mut next_write_pos } => {
self.data[next_write_pos] = value;
next_write_pos += 1;
if next_write_pos >= self.data.len() {
self.pos = BufferState::Cycle { next_write_pos: 0 };
} else {
self.pos = BufferState::Cycle(pos);
self.pos = BufferState::Cycle { next_write_pos };
}
}
BufferState::Empty => {
@ -58,14 +59,16 @@ impl<T> CycledBuffer<T> {
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::Filling { .. } => return CycledIterator::start(collection, 0, getter),
BufferState::Cycle { next_write_pos } => {
return CycledIterator::start(collection, next_write_pos, 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());
return Self::_iter(self.pos, &self.data, |c, i| &c[i]);
}
pub fn iter_mut(&mut self) -> impl Iterator<Item = &mut T> {
@ -75,6 +78,8 @@ impl<T> CycledBuffer<T> {
}
}
/*
impl<T> Drop for CycledBuffer<T> {
fn drop(&mut self) {
for e in self.data.iter_mut() {
@ -83,7 +88,7 @@ impl<T> Drop for CycledBuffer<T> {
}
}
}
}
}*/
trait Len {
fn len(&self) -> usize;
@ -119,15 +124,16 @@ impl<C: Len, E, G: Fn(&mut C, usize) -> E> CycledIterator<C, E, G> {
if middle > 0 {
return Self {
collection,
state: IteratorState::End { middle },
pos: middle,
state: IteratorState::Start { middle },
pos: middle - 1,
getter,
};
} else {
let pos = collection.len() - 1;
return Self {
collection,
state: IteratorState::Plain,
pos: 0,
pos,
getter,
};
};
@ -148,39 +154,40 @@ impl<C: Len, E, G: Fn(&mut C, usize) -> E> Iterator for CycledIterator<C, E, G>
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 {
match self.pos.checked_sub(1) {
Some(pos) => self.pos = pos,
None => {
self.pos = self.collection.len() - 1;
self.state = IteratorState::End { middle };
}
}
return Some(e);
}
IteratorState::End { middle } => {
let e = (self.getter)(&mut self.collection, self.pos);
if self.pos == middle {
self.state = IteratorState::Done;
}
self.pos -= 1;
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);
if self.pos > 0 {
self.pos -= 1;
} else {
self.state = IteratorState::Done;
return None;
}
return Some(e)
}
}
}
}
#[cfg(test)]
mod _tests {
use super::CycledBuffer;
@ -192,8 +199,8 @@ mod _tests {
b.push(9);
let mut it = b.iter();
assert_eq!(it.next(), Some(&6));
assert_eq!(it.next(), Some(&9));
assert_eq!(it.next(), Some(&6));
assert_eq!(it.next(), None);
}
#[test]
@ -204,8 +211,8 @@ mod _tests {
b.push(2);
let mut it = b.iter();
assert_eq!(it.next(), Some(&5));
assert_eq!(it.next(), Some(&2));
assert_eq!(it.next(), Some(&5));
assert_eq!(it.next(), None);
}
}

View File

@ -1,9 +1,9 @@
mod cycle_buffer;
mod cycled_buffer;
use std::collections::HashSet;
use bgtu_networks_2_gui_abstract::ServersStorage as ServersGuiCtx;
use bgtu_networks_2_network_abstract::{Address, ServersContext as ServersNetworkCtx};
use crate::cycle_buffer::CycledBuffer;
use crate::cycled_buffer::CycledBuffer;
struct ServersStorage<A: Address> {
map: HashSet<A, (String, CycledBuffer<Option<u32>>)>