favilla/
push_buffer.rs

1/// A growable CPU-side buffer.
2/// Can be useful for vertex buffers that are updated often.
3pub struct PushBuffer<T> {
4    data: Vec<T>,
5}
6
7impl<T> PushBuffer<T> {
8    /// Create a new buffer with the given capacity. The capacity has to be > 0.
9    pub fn new(capacity: usize) -> Self {
10        assert!(capacity > 0);
11        Self {
12            data: Vec::with_capacity(capacity),
13        }
14    }
15
16    /// Get the currently used length of the buffer.
17    pub fn len(&self) -> usize {
18        self.data.len()
19    }
20
21    /// True iff the buffer is empty.
22    pub fn is_empty(&self) -> bool {
23        self.data.len() == 0
24    }
25
26    /// Get the total allocated capacity of the buffer.
27    pub fn capacity(&self) -> usize {
28        self.data.capacity()
29    }
30
31    /// Start a new pass.
32    pub fn start_pass(&mut self) -> PushBufferPass<'_, T> {
33        self.data.clear();
34        PushBufferPass::new(self)
35    }
36
37    pub fn data(&self) -> &[T] {
38        &self.data
39    }
40}
41
42/// Supports writing to the underlying `PushBuffer` from a given start index.
43pub struct PushBufferPass<'a, T> {
44    push_buffer: &'a mut PushBuffer<T>,
45}
46
47impl<'a, T> PushBufferPass<'a, T> {
48    /// Create a new pass for the given buffer from the given start index.
49    pub fn new(push_buffer: &'a mut PushBuffer<T>) -> Self {
50        Self { push_buffer }
51    }
52
53    /// Push a new element onto the buffer. This can override existing data or grow the buffer.
54    pub fn push(&mut self, element: T) {
55        self.push_buffer.data.push(element);
56    }
57}
58
59#[cfg(test)]
60mod tests {
61    use super::*;
62
63    #[test]
64    fn push_buffer_grows() {
65        let mut push_buffer = PushBuffer::<u32>::new(4);
66        assert_eq!(push_buffer.len(), 0);
67        assert_eq!(push_buffer.capacity(), 4);
68
69        {
70            let mut pass = push_buffer.start_pass();
71            for i in 0..8 {
72                pass.push(i + 1);
73            }
74        }
75
76        assert_eq!(push_buffer.len(), 8);
77        assert_eq!(push_buffer.data(), &(1..9).collect::<Vec<_>>());
78        assert!(push_buffer.capacity() >= 8);
79
80        {
81            let _pass = push_buffer.start_pass();
82        }
83
84        assert_eq!(push_buffer.len(), 0);
85    }
86}