From 36c51a1b10d3a4c6255e7b31f896f8a002cd88ee Mon Sep 17 00:00:00 2001 From: doryan Date: Sun, 10 Aug 2025 20:46:08 +0400 Subject: [PATCH] new repo --- .gitignore | 8 +++++ Cargo.lock | 7 ++++ Cargo.toml | 5 +++ src/lib.rs | 102 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 122 insertions(+) create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 src/lib.rs diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a5ff07f --- /dev/null +++ b/.gitignore @@ -0,0 +1,8 @@ +/target + + +# Added by cargo +# +# already existing elements were commented out + +#/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..8c3ad26 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,7 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 4 + +[[package]] +name = "ring-buffer" +version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..8321e2f --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,5 @@ +[package] +name = "ring-buffer" +version = "0.1.0" +edition = "2024" + diff --git a/src/lib.rs b/src/lib.rs new file mode 100644 index 0000000..6192dbb --- /dev/null +++ b/src/lib.rs @@ -0,0 +1,102 @@ +// Thanks to Low Byte Productions, I like this channel. +// Youtube: https://www.youtube.com/watch?v=uIJnATS9j_0 + +#[derive(Debug, Clone, Copy)] +pub struct RingBuffer { + buf: [u8; N], + mask: usize, + head: usize, + tail: usize, +} + +impl Default for RingBuffer { + fn default() -> Self { + Self::new() + } +} + +impl RingBuffer { + #[inline] + pub const fn new() -> Self { + if N.is_power_of_two() { + Self { + buf: [0; N], + mask: N - 1, + head: 0, + tail: 0, + } + } else { + panic!("Buffer capacity isn't power of two"); + } + } + + #[inline(always)] + pub fn get_buffer(&self) -> &[u8] { + &self.buf + } + + #[inline(always)] + pub fn is_empty(&self) -> bool { + self.head == self.tail + } + + #[inline(always)] + pub fn is_full(&self) -> bool { + (self.head + 1) & self.mask == self.tail + } + + #[inline(always)] + pub fn capacity(&self) -> usize { + N + } + + #[inline(always)] + pub fn len(&self) -> usize { + self.head.overflowing_sub(self.tail).0 & self.mask + } + + #[inline(always)] + pub fn clear(&mut self) { + self.buf = [0; N]; + self.head = 0; + self.tail = 0; + } + + #[inline(always)] + pub fn push(&mut self, value: u8) -> bool { + let (head, tail) = (self.head, self.tail); + let next_head = (head + 1) & self.mask; + + if next_head == tail { + return false; + } + + self.buf[head] = value; + self.head = next_head; + + true + } + + #[inline(always)] + pub fn pop(&mut self) -> Option { + let (head, mut tail) = (self.head, self.tail); + + if head == tail { + return None; + } + + let value = self.buf[tail]; + tail = (tail + 1) & self.mask; + self.tail = tail; + + Some(value) + } +} + +impl Iterator for RingBuffer { + type Item = u8; + + fn next(&mut self) -> Option { + self.pop() + } +}