summaryrefslogtreecommitdiff
path: root/src/collection.rs
diff options
context:
space:
mode:
authorMica White <botahamec@outlook.com>2024-03-10 18:13:20 -0400
committerMica White <botahamec@outlook.com>2024-03-10 18:13:20 -0400
commit0c519b6c7801aa6a085551c8e144f0336e615870 (patch)
tree19063baecb0b50266c654f4809101e856ee89082 /src/collection.rs
parent61d709c211132adcc5158ded77c17d690ad5f8da (diff)
Better librarification
Diffstat (limited to 'src/collection.rs')
-rw-r--r--src/collection.rs129
1 files changed, 116 insertions, 13 deletions
diff --git a/src/collection.rs b/src/collection.rs
index 34de620..1ee5956 100644
--- a/src/collection.rs
+++ b/src/collection.rs
@@ -1,7 +1,5 @@
-use std::{
- marker::PhantomData,
- ops::{Deref, DerefMut},
-};
+use std::marker::PhantomData;
+use std::ops::{Deref, DerefMut};
use crate::{
key::Keyable,
@@ -9,6 +7,7 @@ use crate::{
};
/// returns `true` if the list contains a duplicate
+#[must_use]
fn contains_duplicates(l: &[usize]) -> bool {
for i in 0..l.len() {
for j in (i + 1)..l.len() {
@@ -26,6 +25,7 @@ fn contains_duplicates(l: &[usize]) -> bool {
/// This could be a tuple of [`Lockable`] types, an array, or a `Vec`. But it
/// can be safely locked without causing a deadlock. To do this, it is very
/// important that no duplicate locks are included within.
+#[derive(Debug, Clone, Copy)]
pub struct LockCollection<L> {
collection: L,
}
@@ -37,15 +37,81 @@ pub struct LockGuard<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable + 'key> {
_phantom: PhantomData<&'key ()>,
}
-impl<L> LockCollection<L> {
- /// Creates a new collections of locks.
- ///
- /// # Safety
- ///
- /// This results in undefined behavior if any locks are presented twice
- /// within this collection.
- pub const unsafe fn new_unchecked(collection: L) -> Self {
- Self { collection }
+impl<'a, L: OwnedLockable<'a>> From<L> for LockCollection<L> {
+ fn from(value: L) -> Self {
+ Self::new(value)
+ }
+}
+
+impl<'a, L: OwnedLockable<'a>> AsRef<L> for LockCollection<L> {
+ fn as_ref(&self) -> &L {
+ &self.collection
+ }
+}
+
+impl<'a, L: OwnedLockable<'a>> AsMut<L> for LockCollection<L> {
+ fn as_mut(&mut self) -> &mut L {
+ &mut self.collection
+ }
+}
+
+impl<'a, L: OwnedLockable<'a>> AsRef<Self> for LockCollection<L> {
+ fn as_ref(&self) -> &Self {
+ self
+ }
+}
+
+impl<'a, L: OwnedLockable<'a>> AsMut<Self> for LockCollection<L> {
+ fn as_mut(&mut self) -> &mut Self {
+ self
+ }
+}
+
+impl<L: IntoIterator> IntoIterator for LockCollection<L> {
+ type Item = L::Item;
+ type IntoIter = L::IntoIter;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.collection.into_iter()
+ }
+}
+
+impl<'a, L> IntoIterator for &'a LockCollection<L>
+where
+ &'a L: IntoIterator,
+{
+ type Item = <&'a L as IntoIterator>::Item;
+ type IntoIter = <&'a L as IntoIterator>::IntoIter;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.collection.into_iter()
+ }
+}
+
+impl<'a, L> IntoIterator for &'a mut LockCollection<L>
+where
+ &'a mut L: IntoIterator,
+{
+ type Item = <&'a mut L as IntoIterator>::Item;
+ type IntoIter = <&'a mut L as IntoIterator>::IntoIter;
+
+ fn into_iter(self) -> Self::IntoIter {
+ self.collection.into_iter()
+ }
+}
+
+impl<'a, L: OwnedLockable<'a>, I: FromIterator<L> + OwnedLockable<'a>> FromIterator<L>
+ for LockCollection<I>
+{
+ fn from_iter<T: IntoIterator<Item = L>>(iter: T) -> Self {
+ let iter: I = iter.into_iter().collect();
+ Self::new(iter)
+ }
+}
+
+impl<'a, E: OwnedLockable<'a> + Extend<L>, L: OwnedLockable<'a>> Extend<L> for LockCollection<E> {
+ fn extend<T: IntoIterator<Item = L>>(&mut self, iter: T) {
+ self.collection.extend(iter)
}
}
@@ -54,6 +120,7 @@ impl<'a, L: OwnedLockable<'a>> LockCollection<L> {
///
/// Because the locks are owned, there's no need to do any checks for
/// duplicate values.
+ #[must_use]
pub const fn new(collection: L) -> Self {
Self { collection }
}
@@ -62,11 +129,25 @@ impl<'a, L: OwnedLockable<'a>> LockCollection<L> {
///
/// Because the locks are owned, there's no need to do any checks for
/// duplicate values.
+ #[must_use]
pub const fn new_ref(collection: &L) -> LockCollection<&L> {
LockCollection { collection }
}
}
+impl<L> LockCollection<L> {
+ /// Creates a new collections of locks.
+ ///
+ /// # Safety
+ ///
+ /// This results in undefined behavior if any locks are presented twice
+ /// within this collection.
+ #[must_use]
+ pub const unsafe fn new_unchecked(collection: L) -> Self {
+ Self { collection }
+ }
+}
+
impl<'a, L: Lockable<'a>> LockCollection<L> {
/// Creates a new collection of locks.
///
@@ -78,6 +159,7 @@ impl<'a, L: Lockable<'a>> LockCollection<L> {
/// This does a check at runtime to make sure that the collection contains
/// no two copies of the same lock. This is an `O(n^2)` operation. Prefer
/// [`LockCollection::new`] or [`LockCollection::new_ref`] instead.
+ #[must_use]
pub fn try_new(collection: L) -> Option<Self> {
let ptrs = collection.get_ptrs();
if contains_duplicates(&ptrs) {
@@ -123,6 +205,27 @@ impl<'a, L: Lockable<'a>> LockCollection<L> {
}
}
+impl<'a, L: 'a> LockCollection<L>
+where
+ &'a L: IntoIterator,
+{
+ /// Returns an iterator over references to each value in the collection.
+ pub fn iter(&'a self) -> <&'a L as IntoIterator>::IntoIter {
+ self.into_iter()
+ }
+}
+
+impl<'a, L: 'a> LockCollection<L>
+where
+ &'a mut L: IntoIterator,
+{
+ /// Returns an iterator over mutable references to each value in the
+ /// collection.
+ pub fn iter_mut(&'a mut self) -> <&'a mut L as IntoIterator>::IntoIter {
+ self.into_iter()
+ }
+}
+
impl<'a, 'key: 'a, L: Lockable<'a>, Key: Keyable> Deref for LockGuard<'a, 'key, L, Key> {
type Target = L::Output;