ringbuffer.rs 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116
  1. /* This file is part of DarkFi (https://dark.fi)
  2. *
  3. * Copyright (C) 2020-2026 Dyne.org foundation
  4. *
  5. * This program is free software: you can redistribute it and/or modify
  6. * it under the terms of the GNU Affero General Public License as
  7. * published by the Free Software Foundation, either version 3 of the
  8. * License, or (at your option) any later version.
  9. *
  10. * This program is distributed in the hope that it will be useful,
  11. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * GNU Affero General Public License for more details.
  14. *
  15. * You should have received a copy of the GNU Affero General Public License
  16. * along with this program. If not, see <https://www.gnu.org/licenses/>.
  17. */
  18. use std::collections::{vec_deque::Iter, VecDeque};
  19. /// A ring buffer of fixed capacity
  20. #[derive(Default, Eq, PartialEq, Clone, Debug)]
  21. pub struct RingBuffer<T, const N: usize>(VecDeque<T>);
  22. impl<T: Eq + PartialEq + Clone, const N: usize> RingBuffer<T, N> {
  23. /// Create a new [`RingBuffer`] with given fixed capacity
  24. pub fn new() -> RingBuffer<T, N> {
  25. Self(VecDeque::with_capacity(N))
  26. }
  27. /// Push an element to the back of the `RingBuffer`, removing
  28. /// the front element in case the buffer is full.
  29. pub fn push(&mut self, value: T) {
  30. if self.0.len() == N {
  31. self.0.pop_front();
  32. }
  33. self.0.push_back(value);
  34. }
  35. /// Returns the current number of items in the buffer
  36. pub fn len(&self) -> usize {
  37. self.0.len()
  38. }
  39. /// Returns true if buffer is empty, false otherwise
  40. pub fn is_empty(&self) -> bool {
  41. self.0.is_empty()
  42. }
  43. /// Removes and returns the oldest item in the buffer
  44. pub fn pop(&mut self) -> Option<T> {
  45. self.0.pop_front()
  46. }
  47. /// Returns a front-to-back iterator
  48. pub fn iter(&self) -> Iter<'_, T> {
  49. self.0.iter()
  50. }
  51. /// Returns true if the buffer contains an element equal to the given value
  52. pub fn contains(&self, x: &T) -> bool {
  53. self.0.contains(x)
  54. }
  55. /// Provides a reference to the back element, or `None` if empty.
  56. pub fn back(&self) -> Option<&T> {
  57. self.0.back()
  58. }
  59. /// Cast the ringbuffer into a vec
  60. pub fn to_vec(&self) -> Vec<T> {
  61. self.0.iter().cloned().collect()
  62. }
  63. /// Rearranges the internal storage of this deque so it is one contiguous slice.
  64. pub fn make_contiguous(&mut self) -> &mut [T] {
  65. self.0.make_contiguous()
  66. }
  67. }
  68. impl<T, const N: usize> std::ops::Index<usize> for RingBuffer<T, N> {
  69. type Output = T;
  70. #[inline]
  71. fn index(&self, index: usize) -> &T {
  72. self.0.get(index).expect("Out of bounds access")
  73. }
  74. }
  75. #[cfg(test)]
  76. mod tests {
  77. use super::*;
  78. #[test]
  79. fn behaviour() {
  80. const BUF_SIZE: usize = 10;
  81. let mut buf = RingBuffer::<usize, BUF_SIZE>::new();
  82. for i in 0..BUF_SIZE {
  83. buf.push(i);
  84. }
  85. assert!(!buf.is_empty());
  86. assert!(buf.len() == BUF_SIZE);
  87. for i in 0..BUF_SIZE {
  88. buf.push(i + 10);
  89. }
  90. assert!(buf.len() == BUF_SIZE);
  91. for (i, v) in buf.iter().enumerate() {
  92. assert_eq!(*v, i + 10);
  93. }
  94. }
  95. }