From 96631acb68dbfe156380356c320179f85f24829a Mon Sep 17 00:00:00 2001 From: MrGunflame Date: Fri, 7 Jun 2024 17:05:59 +0200 Subject: [PATCH 1/3] Add `Deque::{get, get_mut, get_unchecked, get_unchecked_mut}` --- CHANGELOG.md | 1 + src/deque.rs | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 80 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0bea10ba..641530d8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -19,6 +19,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/). - Added `VecView`, the `!Sized` version of `Vec`. - Added pool implementations for 64-bit architectures. - Added `IntoIterator` implementation for `LinearMap` +- Added `Deque::{get, get_mut, get_unchecked, get_unchecked_mut}`. ### Changed diff --git a/src/deque.rs b/src/deque.rs index 9e923539..7f58777f 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -535,6 +535,58 @@ impl Deque { done, } } + + /// Returns a reference to the element at the given index. + /// + /// Index 0 is the front of the `Deque`. + pub fn get(&self, index: usize) -> Option<&T> { + if index < self.len() { + let idx = self.to_physical_index(index); + Some(unsafe { self.buffer.get_unchecked(idx).assume_init_ref() }) + } else { + None + } + } + + /// Returns a mutable reference to the element at the given index. + /// + /// Index 0 is the front of the `Deque`. + pub fn get_mut(&mut self, index: usize) -> Option<&mut T> { + if index < self.len() { + let idx = self.to_physical_index(index); + Some(unsafe { self.buffer.get_unchecked_mut(idx).assume_init_mut() }) + } else { + None + } + } + + /// Returns a reference to the element at the given index without checking if it exists. + /// + /// # Safety + /// + /// The element at the given `index` must exist (i.e. `index < self.len()`). + pub unsafe fn get_unchecked(&self, index: usize) -> &T { + debug_assert!(index < self.len()); + + let idx = self.to_physical_index(index); + self.buffer.get_unchecked(idx).assume_init_ref() + } + + /// Returns a mutable reference to the element at the given index without checking if it exists. + /// + /// # Safety + /// + /// The element at the given `index` must exist (i.e. `index < self.len()`). + pub unsafe fn get_unchecked_mut(&mut self, index: usize) -> &mut T { + debug_assert!(index < self.len()); + + let idx = self.to_physical_index(index); + self.buffer.get_unchecked_mut(idx).assume_init_mut() + } + + fn to_physical_index(&self, index: usize) -> usize { + self.front.wrapping_add(index) % N + } } // Trait implementations @@ -1099,4 +1151,31 @@ mod tests { // Deque contains: 5, 6, 7, 8 assert_eq!(q.as_slices(), ([5, 6, 7, 8].as_slice(), [].as_slice())); } + + #[test] + fn get() { + let mut q: Deque = Deque::new(); + assert_eq!(q.get(0), None); + + q.push_back(0).unwrap(); + assert_eq!(q.get(0), Some(&0)); + assert_eq!(q.get(1), None); + + q.push_back(1).unwrap(); + assert_eq!(q.get(0), Some(&0)); + assert_eq!(q.get(1), Some(&1)); + assert_eq!(q.get(2), None); + + q.pop_front().unwrap(); + assert_eq!(q.get(0), Some(&1)); + assert_eq!(q.get(1), None); + + q.push_back(2).unwrap(); + q.push_back(3).unwrap(); + q.push_back(4).unwrap(); + assert_eq!(q.get(0), Some(&1)); + assert_eq!(q.get(1), Some(&2)); + assert_eq!(q.get(2), Some(&3)); + assert_eq!(q.get(3), Some(&4)); + } } From 66fb0242e36037cc4ec4de3254aa0006892ac82a Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 30 Jun 2024 23:58:58 +0200 Subject: [PATCH 2/3] deque: avoid expensive modulo operation. --- src/deque.rs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/deque.rs b/src/deque.rs index 7f58777f..66ce609d 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -585,7 +585,11 @@ impl Deque { } fn to_physical_index(&self, index: usize) -> usize { - self.front.wrapping_add(index) % N + let mut res = self.front + index; + if res >= N { + res -= N; + } + res } } From 0234ca6074cbad404b18250ef0e89cf58349e5e2 Mon Sep 17 00:00:00 2001 From: Dario Nieuwenhuis Date: Sun, 30 Jun 2024 23:59:13 +0200 Subject: [PATCH 3/3] deque: add get_mut test. --- src/deque.rs | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) diff --git a/src/deque.rs b/src/deque.rs index 66ce609d..b596086d 100644 --- a/src/deque.rs +++ b/src/deque.rs @@ -1182,4 +1182,25 @@ mod tests { assert_eq!(q.get(2), Some(&3)); assert_eq!(q.get(3), Some(&4)); } + + #[test] + fn get_mut() { + let mut q: Deque = Deque::new(); + assert_eq!(q.get(0), None); + + q.push_back(0).unwrap(); + assert_eq!(q.get_mut(0), Some(&mut 0)); + assert_eq!(q.get_mut(1), None); + + q.push_back(1).unwrap(); + assert_eq!(q.get_mut(0), Some(&mut 0)); + assert_eq!(q.get_mut(1), Some(&mut 1)); + assert_eq!(q.get_mut(2), None); + *q.get_mut(0).unwrap() = 42; + *q.get_mut(1).unwrap() = 43; + + assert_eq!(q.pop_front(), Some(42)); + assert_eq!(q.pop_front(), Some(43)); + assert_eq!(q.pop_front(), None); + } }