fixed_circular_buffer/
lib.rs

1#![feature(core)]
2
3extern crate core;
4
5use core::iter::FromIterator;
6use core::{iter,mem,slice};
7
8///Fixed size circular/cyclic/ring buffer
9///
10///A FIFO (first in, first out) queue.
11///It cannot represent an empty buffer.
12///
13///When constructed, the internal `list` must not be empty, and cannot contain invalid (e.g. uninitialized) elements.
14#[derive(Clone,Eq,PartialEq,Hash)]
15pub struct CircularBuffer<T>{
16	list: Box<[T]>,
17	first: usize
18}
19
20impl<T> CircularBuffer<T>{
21	///Returns the number of elements (before starting to loop around).
22	#[inline]
23	pub fn len(&self) -> usize{self.list.len()}
24
25	///Enqueues (push at beginning) the given element at the beginning of the buffer
26	///Dequeues (pop at end) the last element and returns it
27	///This keeps the the buffer length
28	pub fn queue(&mut self,mut elem: T) -> T{
29		let len = self.len();
30		self.first = (self.first + len - 1) % len;
31		mem::swap(unsafe{self.list.get_unchecked_mut(self.first)},&mut elem);
32		elem
33	}
34
35	///Sets the offset for the first element, relative to the currently first element
36	///When `index` is out of range, it loops around
37	pub fn set_first(&mut self,index: usize){
38		self.first = (index + self.first) % self.len();
39	}
40
41	///Returns a reference to the element at the given index
42	///When `index` is out of range, it loops around
43	pub fn get(&self,index: usize) -> &T{
44		let len = self.len();
45		unsafe{self.list.get_unchecked((index + self.first) % len)}
46	}
47
48	///Returns a mutable reference to the element at the given index
49	///When `index` is out of range, it loops around
50	pub fn get_mut(&mut self,index: usize) -> &mut T{
51		let len = self.len();
52		unsafe{self.list.get_unchecked_mut((index + self.first) % len)}
53	}
54
55	///Swaps the two elements at the given indices `a` and `b`.
56	///When `a` or `b` are out of range, they loop around
57	pub fn swap_internal(&mut self,a: usize,b: usize){
58		let len = self.len();
59		self.list.swap((a + self.first) % len,(b + self.first) % len);
60	}
61
62	///Swaps the element at the given index with the specifiied new one.
63	///When `a` or `b` are out of range, they loop around
64	pub fn swap(&mut self,index: usize,mut elem: T) -> T{
65		mem::swap(self.get_mut(index),&mut elem);
66		elem
67	}
68
69	///Returns an iterator over the buffer looping around at the end.
70	///This creates a never ending iterator
71	pub fn iter_circular<'s>(&'s self) -> IterCircular<'s,T>{
72		self.list.iter().cycle().skip(self.first)
73	}
74
75	///Returns an iterator over the buffer without looping around.
76	pub fn iter<'s>(&'s self) -> Iter<'s,T>{
77		self.iter_circular().take(self.len())
78	}
79
80	///Constructs the structure from its raw components
81	///
82	///# Unsafety
83	///
84	///This function is unsafe as there is no guarantee that `first` < `list.len()`, nor whether `list` is non-empty.
85	#[inline]
86	pub unsafe fn from_raw_parts(list: Box<[T]>,first: usize) -> Self{
87		CircularBuffer{list: list,first: first}
88	}
89
90	///Deconstructs the structure into its raw components
91	#[inline]
92	pub fn into_raw_parts(self) -> (Box<[T]>,usize){
93		(self.list,self.first)
94	}
95}
96
97impl<T> From<Vec<T>> for CircularBuffer<T>{
98	#[inline]
99	fn from(vec: Vec<T>) -> Self{
100		debug_assert!(vec.len() > 0);
101		CircularBuffer{
102			list: vec.into_boxed_slice(),
103			first: 0
104		}
105	}
106}
107
108impl<T> From<Box<[T]>> for CircularBuffer<T>{
109	#[inline]
110	fn from(l: Box<[T]>) -> Self{
111		debug_assert!(l.len() > 0);
112		CircularBuffer{
113			list: l,
114			first: 0
115		}
116	}
117}
118
119impl<T> FromIterator<T> for CircularBuffer<T>{
120	#[inline]
121	fn from_iter<I>(i: I) -> Self
122		where I: IntoIterator<Item=T>
123	{
124		CircularBuffer::from(Vec::from_iter(i))
125	}
126}
127
128pub type Iter<'t,T> = iter::Take<IterCircular<'t,T>>;
129pub type IterCircular<'t,T> = iter::Skip<iter::Cycle<slice::Iter<'t,T>>>;
130
131#[test]
132fn test_len(){
133	let l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
134	assert_eq!(l.len(),4);
135
136	let l = CircularBuffer::from(Box::new(['a','b']) as Box<[char]>);
137	assert_eq!(l.len(),2);
138
139	let l = CircularBuffer::from(Box::new(['a']) as Box<[char]>);
140	assert_eq!(l.len(),1);
141}
142
143#[test]
144#[should_panic]
145fn test_len_empty(){
146	let _ = CircularBuffer::from(Box::new([]) as Box<[char]>);
147}
148
149#[test]
150fn test_queue(){
151	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
152	assert_eq!(l.first,0);
153	assert_eq!(&*l.list,&['a','b','c','d']);
154
155	l.queue('9');
156	assert_eq!(l.first,3);
157	assert_eq!(&*l.list,&['a','b','c','9']);
158
159	l.queue('8');
160	assert_eq!(l.first,2);
161	assert_eq!(&*l.list,&['a','b','8','9']);
162
163	l.queue('7');
164	assert_eq!(l.first,1);
165	assert_eq!(&*l.list,&['a','7','8','9']);
166
167	l.queue('6');
168	assert_eq!(l.first,0);
169	assert_eq!(&*l.list,&['6','7','8','9']);
170
171	l.queue('5');
172	assert_eq!(l.first,3);
173	assert_eq!(&*l.list,&['6','7','8','5']);
174
175	l.queue('4');
176	assert_eq!(l.first,2);
177	assert_eq!(&*l.list,&['6','7','4','5']);
178}
179
180#[test]
181fn test_set_first(){
182	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
183	l.set_first(0);
184	assert_eq!(l.first,0);
185
186	l.set_first(1);
187	assert_eq!(l.first,1);
188
189	l.set_first(1);
190	assert_eq!(l.first,2);
191
192	l.set_first(1);
193	assert_eq!(l.first,3);
194
195	l.set_first(1);
196	assert_eq!(l.first,0);
197
198	l.set_first(2);
199	assert_eq!(l.first,2);
200
201	l.set_first(4);
202	assert_eq!(l.first,2);
203}
204
205#[test]
206fn test_get(){
207	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
208	l.set_first(0);
209	assert_eq!(l.first,0);
210	assert_eq!(*l.get(0),'a');
211	assert_eq!(*l.get(1),'b');
212	assert_eq!(*l.get(2),'c');
213	assert_eq!(*l.get(3),'d');
214
215	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
216	l.set_first(1);
217	assert_eq!(l.first,1);
218	assert_eq!(*l.get(0),'b');
219	assert_eq!(*l.get(1),'c');
220	assert_eq!(*l.get(2),'d');
221	assert_eq!(*l.get(3),'a');
222
223	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
224	l.set_first(2);
225	assert_eq!(l.first,2);
226	assert_eq!(*l.get(0),'c');
227	assert_eq!(*l.get(1),'d');
228	assert_eq!(*l.get(2),'a');
229	assert_eq!(*l.get(3),'b');
230
231	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
232	l.set_first(3);
233	assert_eq!(l.first,3);
234	assert_eq!(*l.get(0),'d');
235	assert_eq!(*l.get(1),'a');
236	assert_eq!(*l.get(2),'b');
237	assert_eq!(*l.get(3),'c');
238
239	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
240	l.set_first(4);
241	assert_eq!(l.first,0);
242	assert_eq!(*l.get(0),'a');
243	assert_eq!(*l.get(1),'b');
244	assert_eq!(*l.get(2),'c');
245	assert_eq!(*l.get(3),'d');
246
247	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
248	l.set_first(5);
249	assert_eq!(l.first,1);
250	assert_eq!(*l.get(0),'b');
251	assert_eq!(*l.get(1),'c');
252	assert_eq!(*l.get(2),'d');
253	assert_eq!(*l.get(3),'a');
254}
255
256#[test]
257fn test_get_mut(){
258	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
259	l.set_first(0);
260	assert_eq!(l.first,0);
261	assert_eq!(*l.get_mut(0),'a');
262	assert_eq!(*l.get_mut(1),'b');
263	assert_eq!(*l.get_mut(2),'c');
264	assert_eq!(*l.get_mut(3),'d');
265
266	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
267	l.set_first(1);
268	assert_eq!(l.first,1);
269	assert_eq!(*l.get_mut(0),'b');
270	assert_eq!(*l.get_mut(1),'c');
271	assert_eq!(*l.get_mut(2),'d');
272	assert_eq!(*l.get_mut(3),'a');
273
274	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
275	l.set_first(2);
276	assert_eq!(l.first,2);
277	assert_eq!(*l.get_mut(0),'c');
278	assert_eq!(*l.get_mut(1),'d');
279	assert_eq!(*l.get_mut(2),'a');
280	assert_eq!(*l.get_mut(3),'b');
281
282	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
283	l.set_first(3);
284	assert_eq!(l.first,3);
285	assert_eq!(*l.get_mut(0),'d');
286	assert_eq!(*l.get_mut(1),'a');
287	assert_eq!(*l.get_mut(2),'b');
288	assert_eq!(*l.get_mut(3),'c');
289
290	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
291	l.set_first(4);
292	assert_eq!(l.first,0);
293	assert_eq!(*l.get_mut(0),'a');
294	assert_eq!(*l.get_mut(1),'b');
295	assert_eq!(*l.get_mut(2),'c');
296	assert_eq!(*l.get_mut(3),'d');
297
298	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
299	l.set_first(5);
300	assert_eq!(l.first,1);
301	assert_eq!(*l.get_mut(0),'b');
302	assert_eq!(*l.get_mut(1),'c');
303	assert_eq!(*l.get_mut(2),'d');
304	assert_eq!(*l.get_mut(3),'a');
305}
306
307#[test]
308fn test_swap(){
309	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
310	assert_eq!(&*l.list,&['a','b','c','d']);
311
312	l.swap(0,'0');
313	assert_eq!(&*l.list,&['0','b','c','d']);
314
315	l.swap(1,'1');
316	assert_eq!(&*l.list,&['0','1','c','d']);
317
318	l.swap(2,'2');
319	assert_eq!(&*l.list,&['0','1','2','d']);
320
321	l.swap(3,'3');
322	assert_eq!(&*l.list,&['0','1','2','3']);
323
324	l.swap(4,'4');
325	assert_eq!(&*l.list,&['4','1','2','3']);
326
327	l.swap(5,'5');
328	assert_eq!(&*l.list,&['4','5','2','3']);
329
330	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
331	l.set_first(1);
332	assert_eq!(&*l.list,&['a','b','c','d']);
333
334	l.swap(0,'0');
335	assert_eq!(&*l.list,&['a','0','c','d']);
336
337	l.swap(1,'1');
338	assert_eq!(&*l.list,&['a','0','1','d']);
339
340	l.swap(2,'2');
341	assert_eq!(&*l.list,&['a','0','1','2']);
342
343	l.swap(3,'3');
344	assert_eq!(&*l.list,&['3','0','1','2']);
345
346	l.swap(4,'4');
347	assert_eq!(&*l.list,&['3','4','1','2']);
348
349	l.swap(5,'5');
350	assert_eq!(&*l.list,&['3','4','5','2']);
351}
352
353#[test]
354fn test_swap_internal(){
355	let mut l = CircularBuffer::from(Box::new(['a','b','c','d']) as Box<[char]>);
356	assert_eq!(&*l.list,&['a','b','c','d']);
357
358	l.swap_internal(0,3);
359	assert_eq!(&*l.list,&['d','b','c','a']);
360
361	l.swap_internal(3,0);
362	assert_eq!(&*l.list,&['a','b','c','d']);
363
364	l.swap_internal(1,2);
365	assert_eq!(&*l.list,&['a','c','b','d']);
366
367	l.swap_internal(2,1);
368	assert_eq!(&*l.list,&['a','b','c','d']);
369
370	l.swap_internal(0,5);
371	assert_eq!(&*l.list,&['b','a','c','d']);
372
373	l.swap_internal(5,0);
374	assert_eq!(&*l.list,&['a','b','c','d']);
375}
376
377#[test]
378fn test_iter(){
379	let l = unsafe{CircularBuffer::from_raw_parts(Box::new(['a','b','c']) as Box<[char]>,0)};
380	let mut i = l.iter();
381
382	assert_eq!(*i.next().unwrap(),'a');
383	assert_eq!(*i.next().unwrap(),'b');
384	assert_eq!(*i.next().unwrap(),'c');
385	assert!(i.next().is_none());
386
387	let l = unsafe{CircularBuffer::from_raw_parts(Box::new(['a','b','c']) as Box<[char]>,1)};
388	let mut i = l.iter();
389
390	assert_eq!(*i.next().unwrap(),'b');
391	assert_eq!(*i.next().unwrap(),'c');
392	assert_eq!(*i.next().unwrap(),'a');
393	assert!(i.next().is_none());
394
395	let l = unsafe{CircularBuffer::from_raw_parts(Box::new(['a','b','c']) as Box<[char]>,2)};
396	let mut i = l.iter();
397
398	assert_eq!(*i.next().unwrap(),'c');
399	assert_eq!(*i.next().unwrap(),'a');
400	assert_eq!(*i.next().unwrap(),'b');
401	assert!(i.next().is_none());
402}
403
404#[test]
405fn test_iter_circular(){
406	let l = unsafe{CircularBuffer::from_raw_parts(Box::new(['a','b','c']) as Box<[char]>,0)};
407	let mut i = l.iter_circular();
408
409	assert_eq!(*i.next().unwrap(),'a');
410	assert_eq!(*i.next().unwrap(),'b');
411	assert_eq!(*i.next().unwrap(),'c');
412	assert_eq!(*i.next().unwrap(),'a');
413	assert_eq!(*i.next().unwrap(),'b');
414	assert_eq!(*i.next().unwrap(),'c');
415	assert_eq!(*i.next().unwrap(),'a');
416	assert_eq!(*i.next().unwrap(),'b');
417	assert_eq!(*i.next().unwrap(),'c');
418
419	let l = unsafe{CircularBuffer::from_raw_parts(Box::new(['a','b','c']) as Box<[char]>,1)};
420	let mut i = l.iter_circular();
421
422	assert_eq!(*i.next().unwrap(),'b');
423	assert_eq!(*i.next().unwrap(),'c');
424	assert_eq!(*i.next().unwrap(),'a');
425	assert_eq!(*i.next().unwrap(),'b');
426	assert_eq!(*i.next().unwrap(),'c');
427	assert_eq!(*i.next().unwrap(),'a');
428	assert_eq!(*i.next().unwrap(),'b');
429	assert_eq!(*i.next().unwrap(),'c');
430	assert_eq!(*i.next().unwrap(),'a');
431
432	let l = unsafe{CircularBuffer::from_raw_parts(Box::new(['a','b','c']) as Box<[char]>,2)};
433	let mut i = l.iter_circular();
434
435	assert_eq!(*i.next().unwrap(),'c');
436	assert_eq!(*i.next().unwrap(),'a');
437	assert_eq!(*i.next().unwrap(),'b');
438	assert_eq!(*i.next().unwrap(),'c');
439	assert_eq!(*i.next().unwrap(),'a');
440	assert_eq!(*i.next().unwrap(),'b');
441	assert_eq!(*i.next().unwrap(),'c');
442	assert_eq!(*i.next().unwrap(),'a');
443	assert_eq!(*i.next().unwrap(),'b');
444}