ArrayDeque
A collection of fixed-capacity circular buffer (ring buffer) implementations providing efficient double-ended queue operations. This crate offers both heap-allocated and stack-allocated variants, making it suitable for a wide range of use cases from general applications to embedded systems.
Implementations
This crate provides two deque implementations:
ArrayDeque
: Heap-allocated with runtime-determined capacityStackArrayDeque
: Stack-allocated with compile-time fixed capacity
Both implementations use circular buffers for efficient O(1) operations at both ends and will overwrite old elements when full.
Features
- Fixed Capacity: Memory usage is determined at creation/compile time
- Circular Buffer: Efficient O(1) operations at both ends
- Overwrite Behavior: When full, new elements overwrite the oldest ones
- Zero Allocations: After initial allocation, no further memory allocations
- Stack Allocation:
StackArrayDeque
uses no heap memory at all - No-std Support: Works in
no_std
environments (withalloc
forArrayDeque
) - Serde Support: Optional serialization/deserialization (with
serde
feature) - Iterator Support: Full iterator implementation with
IntoIterator
- Index Access: Direct element access via indexing
- Clone Support: Deep cloning of the entire deque
Quick Start
Add this to your Cargo.toml
:
[]
= "0.3.1"
# For serde support
= { = "0.3.1", = ["serde"] }
# For no_std environments (requires alloc for ArrayDeque)
= { = "0.3.1", = false }
# For no_std with serde
= { = "0.3.1", = false, = ["serde"] }
Usage
Choosing Between ArrayDeque and StackArrayDeque
Use ArrayDeque
when:
- Capacity is determined at runtime
- You need flexibility in sizing
- Memory usage is not severely constrained
- Working in environments with heap allocation
Use StackArrayDeque
when:
- Capacity is known at compile time
- You want zero heap allocations
- Working in embedded or no-heap environments
- Maximum performance and predictability is required
ArrayDeque (Heap-allocated)
use ArrayDeque;
// Create a deque with capacity for 5 elements
let mut deque = new;
// Add elements to the back
deque.push_back;
deque.push_back;
deque.push_back;
// Add elements to the front
deque.push_front;
// Access elements by index (0 = front, len-1 = back)
assert_eq!; // front element
assert_eq!;
assert_eq!;
assert_eq!; // back element
// Remove elements
assert_eq!;
assert_eq!;
StackArrayDeque (Stack-allocated)
use StackArrayDeque;
// Create a stack-allocated deque with compile-time capacity
let mut deque: = new;
// Same API as ArrayDeque
deque.push_back;
deque.push_back;
deque.push_back;
deque.push_front;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
assert_eq!;
Overflow Behavior
Both implementations behave identically when reaching capacity:
use ;
// Heap-allocated version
let mut heap_deque = new;
heap_deque.push_back;
heap_deque.push_back;
heap_deque.push_back;
heap_deque.push_back; // Overwrites 1
// Deque is now: [2, 3, 4]
// Stack-allocated version
let mut stack_deque: = new;
stack_deque.push_back;
stack_deque.push_back;
stack_deque.push_back;
stack_deque.push_back; // Overwrites 1
// Deque is now: [2, 3, 4]
Iteration
Both types support the same iteration patterns:
use ;
// ArrayDeque
let mut heap_deque = new;
heap_deque.extend;
// StackArrayDeque
let mut stack_deque: = new;
for i in 1..=5
// Both support iteration by reference
for item in &heap_deque
for item in stack_deque.iter
Creating from Collections
ArrayDeque
supports creation from various collections:
use ArrayDeque;
// From array
let deque = from;
// From vector
let deque = from;
// From slice
let slice = &;
let deque = from;
// From iterator
let deque: = .collect;
StackArrayDeque
must be created with new()
and populated manually:
use StackArrayDeque;
let mut deque: = new;
for i in 1..=5
No-std Usage
Both types work in no_std
environments:
extern crate alloc; // Only needed for ArrayDeque
use ;
use vec;
// ArrayDeque requires alloc
let mut heap_deque = new;
heap_deque.extend;
// StackArrayDeque works without alloc
let mut stack_deque: = new;
stack_deque.push_back;
stack_deque.push_back;
stack_deque.push_back;
Serde Support
With the serde
feature enabled, both types support serialization:
use ;
use serde_json;
// ArrayDeque
let mut heap_deque = new;
heap_deque.extend;
let json = to_string.unwrap;
// StackArrayDeque
let mut stack_deque: = new;
stack_deque.push_back;
stack_deque.push_back;
stack_deque.push_back;
let json_stack = to_string.unwrap;
API Overview
Both ArrayDeque
and StackArrayDeque
share the same core API:
Core Methods
new()
- Create a new deque (new(capacity)
forArrayDeque
,new()
forStackArrayDeque
)push_back(item)
- Add element to the backpush_front(item)
- Add element to the frontpop_back()
- Remove and return back elementpop_front()
- Remove and return front element
Capacity and State
len()
- Number of elements currently storedcapacity()
- Maximum number of elementsis_empty()
- Check if deque has no elementsis_full()
- Check if deque is at capacityclear()
- Remove all elements
Access and Iteration
[index]
- Direct element access and mutationiter()
- Iterator over element references
ArrayDeque Additional Methods
into_iter()
- Consuming iteratorextend()
- Extend from iterator- Various
From
implementations
Performance
All core operations are O(1) for both implementations:
push_back
/push_front
: O(1)pop_back
/pop_front
: O(1)- Index access: O(1)
len
/is_empty
/is_full
: O(1)
Use Cases
Heap-Allocated ArrayDeque
- Audio/Video Buffers: Variable-size buffers for streaming data
- Dynamic Circular Logs: Runtime-determined log sizes
- General Applications: When capacity is determined at runtime
Stack-Allocated StackArrayDeque
- Embedded Systems: Zero heap allocation, predictable memory usage
- Real-time Systems: Maximum performance, no allocation overhead
- Fixed-size Buffers: When capacity is known at compile time
- ISR-safe Operations: No heap allocation means no malloc/free in interrupts
Comparison Table
Feature | ArrayDeque |
StackArrayDeque |
VecDeque |
---|---|---|---|
Allocation | Heap | Stack | Heap |
Capacity | Runtime-fixed | Compile-time fixed | Dynamic, grows |
Memory | Predictable after init | Completely predictable | May reallocate |
Overflow | Overwrites oldest | Overwrites oldest | Grows capacity |
Performance | Consistent O(1) | Consistent O(1) | Amortized O(1) |
No-std | Supported (with alloc ) |
Fully supported | Requires std |
ISR-safe | No (heap allocation) | Yes | No |
License
This project is licensed under the MIT License.
Contributing
Contributions are welcome! Please feel free to submit a Pull Request.