media_core/
circular_buffer.rs1use crate::{Error, Result};
2
3pub struct CircularBuffer<T = u8> {
4 buffer: Vec<T>,
5 read_pos: usize,
6 write_pos: usize,
7 len: usize,
8}
9
10impl<T: Default + Copy> CircularBuffer<T> {
11 pub fn new(capacity: usize) -> Self {
12 Self {
13 buffer: vec![T::default(); capacity],
14 read_pos: 0,
15 write_pos: 0,
16 len: 0,
17 }
18 }
19
20 #[inline]
21 pub fn len(&self) -> usize {
22 self.len
23 }
24
25 #[inline]
26 pub fn is_empty(&self) -> bool {
27 self.len == 0
28 }
29
30 #[inline]
31 pub fn capacity(&self) -> usize {
32 self.buffer.len()
33 }
34
35 #[inline]
36 pub fn available(&self) -> usize {
37 self.capacity() - self.len
38 }
39
40 pub fn grow(&mut self, capacity: usize) -> Result<()> {
41 if self.capacity() >= capacity {
42 return Ok(());
43 }
44
45 let new_capacity = capacity.max(self.capacity() * 2);
46
47 if self.read_pos + self.len <= self.capacity() {
48 if self.write_pos == 0 && self.len > 0 {
49 let pos = self.capacity();
50 self.buffer.resize(new_capacity, T::default());
51 self.write_pos = pos;
52 } else {
53 self.buffer.resize(new_capacity, T::default());
54 }
55 } else {
56 let mut new_buffer = vec![T::default(); new_capacity];
57 let len = self.len;
58
59 if len > 0 {
60 self.read_to_slice(&mut new_buffer[..len]);
61 }
62
63 self.buffer = new_buffer;
64 self.read_pos = 0;
65 self.write_pos = len;
66 self.len = len;
67 }
68
69 Ok(())
70 }
71
72 pub fn write(&mut self, buf: &[T]) -> Result<usize> {
73 if buf.is_empty() {
74 return Err(Error::WriteFailed("input buffer is empty".to_string()));
75 }
76
77 if self.available() < buf.len() {
78 self.grow(self.len + buf.len())?;
79 }
80
81 let write_len = buf.len().min(self.available());
82 let end_pos = self.write_pos + write_len;
83
84 if end_pos <= self.capacity() {
85 self.buffer[self.write_pos..end_pos].copy_from_slice(&buf[..write_len]);
86 self.write_pos = end_pos % self.capacity();
87 } else {
88 let chunk_len = self.capacity() - self.write_pos;
89 self.buffer[self.write_pos..].copy_from_slice(&buf[..chunk_len]);
90 self.buffer[..write_len - chunk_len].copy_from_slice(&buf[chunk_len..write_len]);
91 self.write_pos = (write_len - chunk_len) % self.capacity();
92 }
93
94 self.len += write_len;
95
96 Ok(write_len)
97 }
98
99 pub fn read(&mut self, buf: &mut [T]) -> Result<usize> {
100 if buf.is_empty() {
101 return Err(Error::ReadFailed("output buffer is empty".to_string()));
102 }
103
104 let read_len = buf.len().min(self.len);
105 if read_len == 0 {
106 return Ok(0);
107 }
108
109 self.read_to_slice(&mut buf[..read_len]);
110 Ok(read_len)
111 }
112
113 fn read_to_slice(&mut self, buf: &mut [T]) {
114 let read_len = buf.len();
115 let end_pos = self.read_pos + read_len;
116
117 if end_pos <= self.capacity() {
118 buf.copy_from_slice(&self.buffer[self.read_pos..end_pos]);
119 self.read_pos = end_pos % self.capacity();
120 } else {
121 let chunk_len = self.capacity() - self.read_pos;
122 buf[..chunk_len].copy_from_slice(&self.buffer[self.read_pos..]);
123 buf[chunk_len..].copy_from_slice(&self.buffer[..read_len - chunk_len]);
124 self.read_pos = (read_len - chunk_len) % self.capacity();
125 }
126
127 self.len -= read_len;
128 }
129
130 pub fn peek(&self, buf: &mut [T]) -> Result<usize> {
131 if buf.is_empty() {
132 return Err(Error::ReadFailed("output buffer is empty".to_string()));
133 }
134
135 let peek_len = buf.len().min(self.len);
136 if peek_len == 0 {
137 return Ok(0);
138 }
139
140 let end_pos = self.read_pos + peek_len;
141
142 if end_pos <= self.capacity() {
143 buf.copy_from_slice(&self.buffer[self.read_pos..end_pos]);
144 } else {
145 let chunk_len = self.capacity() - self.read_pos;
146 buf[..chunk_len].copy_from_slice(&self.buffer[self.read_pos..]);
147 buf[chunk_len..].copy_from_slice(&self.buffer[..peek_len - chunk_len]);
148 }
149
150 Ok(peek_len)
151 }
152
153 pub fn consume(&mut self, len: usize) -> usize {
154 let consume_len = len.min(self.len);
155 self.read_pos = (self.read_pos + consume_len) % self.capacity();
156 self.len -= consume_len;
157 consume_len
158 }
159
160 pub fn clear(&mut self) {
161 self.read_pos = 0;
162 self.write_pos = 0;
163 self.len = 0;
164 }
165}