Rust challenge 10/100 - Queue Port
Table of content
What is this?
The rules of the game are explained in my original post.
Up until now I have given my self small challenge to solve. It seems to me that I am doing to tasks, learning Rust but also solving problems. My initial aim however was to learn Rust. To try and improve the focus of my endeavor lets try re-writing existing code instead of solving a problem and writing new code.
10th Challenge
Challenge
- port the queue implementation in c to Rust.
Solution
So I started with this and it became apparent that it was maybe not really a suitable translation challenge. After
so trying back and forward I had a look at the std::collections
implementation and came across the following note:
// NOTE: It is almost always better to use `Vec` or `VecDeque` because
/// array-based containers are generally faster,
/// more memory efficient, and make better use of CPU cache.
Note the Rust implementation uses the type NonNull
and the NonNull
documentation says to use *mut T
as this is guaranteed to never be Null. If we look further, the implementation is done using unsafe
which
is not something I would like to do right now. Part of the reason I’m learning Rust is so my code may be safe.
Therefore I will just create a wrapper with the same API as the code I’m trying to translate.
use std::collections::VecDeque;
fn main() {
let mut q:Queue<i32>=Queue::new();
let e1:QueueEntry<i32> = QueueEntry{ data: 3 };
assert!(q.is_empty());
q.push_head(e1);
assert_eq!(q.peek_head().unwrap().data,3);
assert_eq!(q.pop_head().unwrap().data,3);
let e1 = QueueEntry{ data: 4 };
q.push_tail(e1);
assert_eq!(q.peek_tail().unwrap().data,4);
assert_eq!(q.pop_tail().unwrap().data,4);
q.free();
assert!(q.is_empty());
}
struct QueueEntry<T>{
data:T,
}
struct Queue<T>{
data:VecDeque<QueueEntry<T>>
}
impl <T> Queue<T> {
fn free (&mut self){
self.data.clear();
}
fn push_head(&mut self,entry:QueueEntry<T>){
self.data.push_back(entry);
}
fn pop_head(&mut self) -> Option<QueueEntry<T>> {
self.data.pop_back()
}
fn peek_head(&mut self) -> Option<&QueueEntry<T>> {
self.data.back()
}
fn push_tail(&mut self,entry:QueueEntry<T>){
self.data.push_front(entry);
}
fn pop_tail(&mut self) -> Option<QueueEntry<T>>{
self.data.pop_front()
}
fn peek_tail(&mut self) -> Option<&QueueEntry<T>>{
self.data.back()
}
fn is_empty(&mut self) -> bool {
self.data.is_empty()
}
fn new() -> Queue<T>{
Queue{
data: Default::default()
}
}
}
I feel like this was a relatively valuable lesson. I will try to keep up with this translating code challenge method and see how it goes.
See github and playground