Skip to main content

rill_core/buffer/
buffer_trait.rs

1//! # Buffer trait — common interface for all signal buffer types
2//!
3//! Unified trait covering both storage buffers (fixed-size, heap-allocated)
4//! and queue-style buffers (pipe, delay, fan-out, fan-in, ring).
5//!
6//! Generic over [`crate::math::Scalar`] — supports f32, f64, and integer types.
7
8use core::ops::{Deref, DerefMut};
9
10use crate::buffer::BufferStats;
11use crate::math::Scalar;
12
13/// Common interface for all buffer types used in the signal graph.
14pub trait Buffer<T: Scalar> {
15    /// Maximum number of elements the buffer can hold.
16    fn capacity(&self) -> usize;
17
18    /// Current number of elements in the buffer.
19    fn len(&self) -> usize;
20
21    /// Whether the buffer is empty (`len() == 0`).
22    fn is_empty(&self) -> bool {
23        self.len() == 0
24    }
25
26    /// Whether the buffer is full (`len() == capacity()`).
27    fn is_full(&self) -> bool {
28        self.len() == self.capacity()
29    }
30
31    /// Read-only access to the buffer data.
32    fn as_slice(&self) -> &[T];
33
34    /// Mutable access to the buffer data.
35    fn as_mut_slice(&mut self) -> &mut [T];
36
37    /// Fill the entire buffer with a value.
38    fn fill(&mut self, value: T);
39
40    /// Copy data from a slice. Copies `min(src.len(), self.len())` samples.
41    fn copy_from(&mut self, src: &[T]);
42
43    /// Remove all items from the buffer.
44    fn clear(&mut self);
45
46    /// Snapshot of performance statistics.
47    fn stats(&self) -> BufferStats {
48        BufferStats::new()
49    }
50
51    /// Reset performance counters (not the data).
52    fn reset_stats(&mut self) {}
53}
54
55// ============================================================================
56// FixedBuffer — compile-time fixed size, stack-allocated
57// ============================================================================
58
59/// Fixed-size buffer on the stack — default per-port buffer.
60///
61/// 16-byte aligned for direct SIMD loads/stores via `_mm_load_ps` / `_mm256_load_ps`.
62#[derive(Debug, Clone)]
63#[repr(align(16))]
64pub struct FixedBuffer<T, const SIZE: usize> {
65    data: [T; SIZE],
66}
67
68impl<T: Scalar, const SIZE: usize> FixedBuffer<T, SIZE> {
69    /// Create a new buffer filled with `T::default()`.
70    pub fn new() -> Self {
71        Self {
72            data: [T::default(); SIZE],
73        }
74    }
75
76    /// Create a buffer from a fixed-size array.
77    pub fn from_array(data: [T; SIZE]) -> Self {
78        Self { data }
79    }
80
81    /// Create a buffer from a slice, truncating or padding with `T::default()` as needed.
82    pub fn from_slice(slice: &[T]) -> Self {
83        let mut data = [T::default(); SIZE];
84        let len = slice.len().min(SIZE);
85        data[..len].copy_from_slice(&slice[..len]);
86        Self { data }
87    }
88
89    /// Return a reference to the inner array.
90    pub fn as_array(&self) -> &[T; SIZE] {
91        &self.data
92    }
93
94    /// Return a mutable reference to the inner array.
95    pub fn as_mut_array(&mut self) -> &mut [T; SIZE] {
96        &mut self.data
97    }
98}
99
100impl<T: Scalar, const SIZE: usize> Default for FixedBuffer<T, SIZE> {
101    fn default() -> Self {
102        Self::new()
103    }
104}
105
106impl<T: Scalar, const SIZE: usize> Deref for FixedBuffer<T, SIZE> {
107    type Target = [T; SIZE];
108    fn deref(&self) -> &Self::Target {
109        &self.data
110    }
111}
112
113impl<T: Scalar, const SIZE: usize> DerefMut for FixedBuffer<T, SIZE> {
114    fn deref_mut(&mut self) -> &mut Self::Target {
115        &mut self.data
116    }
117}
118
119impl<T: Scalar, const SIZE: usize> From<[T; SIZE]> for FixedBuffer<T, SIZE> {
120    fn from(data: [T; SIZE]) -> Self {
121        Self::from_array(data)
122    }
123}
124
125impl<T: Scalar, const SIZE: usize> Buffer<T> for FixedBuffer<T, SIZE> {
126    fn capacity(&self) -> usize {
127        SIZE
128    }
129
130    fn len(&self) -> usize {
131        SIZE
132    }
133
134    fn as_slice(&self) -> &[T] {
135        &self.data
136    }
137
138    fn as_mut_slice(&mut self) -> &mut [T] {
139        &mut self.data
140    }
141
142    fn fill(&mut self, value: T) {
143        self.data.fill(value);
144    }
145
146    fn copy_from(&mut self, src: &[T]) {
147        let len = src.len().min(SIZE);
148        self.data[..len].copy_from_slice(&src[..len]);
149    }
150
151    fn clear(&mut self) {
152        self.data.fill(T::default());
153    }
154}
155
156// ============================================================================
157// HeapBuffer — runtime-sized, heap-allocated
158// ============================================================================
159
160/// Heap-allocated buffer with runtime-determined size.
161///
162/// Used for resources whose size is determined from data
163/// (loaded samples, configuration).
164#[derive(Debug, Clone)]
165pub struct HeapBuffer<T> {
166    data: Vec<T>,
167}
168
169impl<T: Scalar> HeapBuffer<T> {
170    /// Create a new buffer with `size` samples, all initialized to `T::default()`.
171    pub fn new(size: usize) -> Self {
172        Self {
173            data: vec![T::default(); size],
174        }
175    }
176
177    /// Create a buffer from an existing `Vec`, taking ownership.
178    pub fn from_vec(data: Vec<T>) -> Self {
179        Self { data }
180    }
181}
182
183impl<T: Scalar> Buffer<T> for HeapBuffer<T> {
184    fn capacity(&self) -> usize {
185        self.data.capacity()
186    }
187
188    fn len(&self) -> usize {
189        self.data.len()
190    }
191
192    fn as_slice(&self) -> &[T] {
193        &self.data
194    }
195
196    fn as_mut_slice(&mut self) -> &mut [T] {
197        &mut self.data
198    }
199
200    fn fill(&mut self, value: T) {
201        self.data.fill(value);
202    }
203
204    fn copy_from(&mut self, src: &[T]) {
205        let len = src.len().min(self.data.len());
206        self.data[..len].copy_from_slice(&src[..len]);
207    }
208
209    fn clear(&mut self) {
210        self.data.clear();
211    }
212}