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

View File

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