Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add unstable sorting functions #2

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
198 changes: 171 additions & 27 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@
//! - You need to share the array across multiple threads *(you may use `Vec<Mutex<T>>` or `Arc<Vec<Mutex<T>>>` instead)*

use std::cell::{Cell, UnsafeCell};
use std::cmp::Ordering;
use std::fmt::{self, Debug, Display};
use std::ops::{Deref, DerefMut};

Expand Down Expand Up @@ -102,7 +103,7 @@ impl<T> VecCell<T> {
Self {
mut_borrow: Cell::new(None),
borrows: Cell::new(0),
inner: Vec::with_capacity(capacity)
inner: Vec::with_capacity(capacity),
}
}

Expand Down Expand Up @@ -356,7 +357,10 @@ impl<T> VecCell<T> {
/// assert_eq!(s[1], 2);
/// assert!(s.get(2).is_none());
/// ```
pub fn borrow_range<'b, R: std::ops::RangeBounds<usize>>(&'b self, range: R) -> Option<VecRef<'b, [T]>> {
pub fn borrow_range<'b, R: std::ops::RangeBounds<usize>>(
&'b self,
range: R,
) -> Option<VecRef<'b, [T]>> {
VecRef::from_range(self, range)
}

Expand Down Expand Up @@ -491,9 +495,7 @@ impl<T> VecCell<T> {
/// std::mem::drop(x);
/// ```
pub fn try_iter<'b>(&'b self) -> impl Iterator<Item = Option<VecRef<'b, T>>> {
(0..self.len()).map(|index| {
self.borrow(index)
})
(0..self.len()).map(|index| self.borrow(index))
}

/// Resets the [`borrows`](VecCell::borrows) and [`mut_borrow`](VecCell::mut_borrow) counters.
Expand Down Expand Up @@ -547,11 +549,134 @@ impl<T> VecCell<T> {
/// If no reference was [forgotten](std::mem::forget), then `mut_borrow == None` and `borrows == 0`.
#[inline]
pub fn into_raw_parts(self) -> (Vec<UnsafeCell<T>>, Option<usize>, usize) {
(self.inner, self.mut_borrow.into_inner(), self.borrows.into_inner())
(
self.inner,
self.mut_borrow.into_inner(),
self.borrows.into_inner(),
)
}

// == Unsafe functions section ==

/// Sorts the vector, but might not preserve the order of equal elements.
///
/// This sort uses the same implementation as `[T]::sort_unstable_by`.
///
/// ## Example
///
/// ```
/// # use veccell::*;
/// let mut vec: VecCell<usize> = VecCell::new();
///
/// vec.push(30);
/// vec.push(0);
/// vec.push(20);
/// vec.push(10);
///
/// vec.sort_unstable();
///
/// assert_eq!(vec.borrow(0).unwrap(), 0);
/// assert_eq!(vec.borrow(1).unwrap(), 10);
/// assert_eq!(vec.borrow(2).unwrap(), 20);
/// assert_eq!(vec.borrow(3).unwrap(), 30);
/// ```
pub fn sort_unstable(&mut self)
where
T: Ord,
{
self.sort_unstable_by(|a, b| a.cmp(b))
}

/// Sorts the vector with a comparator function, but might not preserve the order of
/// equal elements.
///
/// This sort uses the same implementation as `[T]::sort_unstable_by`.
///
/// ## Example
///
/// ```
/// # use veccell::*;
/// let mut vec: VecCell<usize> = VecCell::new();
///
/// vec.push(30);
/// vec.push(0);
/// vec.push(20);
/// vec.push(10);
///
/// vec.sort_unstable_by(|a, b| b.cmp(a));
///
/// assert_eq!(vec.borrow(0).unwrap(), 30);
/// assert_eq!(vec.borrow(1).unwrap(), 20);
/// assert_eq!(vec.borrow(2).unwrap(), 10);
/// assert_eq!(vec.borrow(3).unwrap(), 0);
/// ```
pub fn sort_unstable_by<F>(&mut self, mut compare: F)
where
T: Ord,
F: FnMut(&T, &T) -> Ordering,
{
assert_eq!(
self.borrows.get(),
0,
"Sorting requires that no item is currently borrowed"
);
assert!(
self.mut_borrow.get().is_none(),
"Sorting requires that no item is currently (mutably) borrowed"
);
self.inner.sort_unstable_by(|a, b| {
// SAFETY: self is borrowed mutably and a and b are not itself changed.
let a = unsafe { &*a.get() };
let b = unsafe { &*b.get() };
compare(a, b)
});
}

/// Sorts the vector with a key extraction function, but might not preserve the order of
/// equal elements.
///
/// This sort uses the same implementation as `[T]::sort_unstable_by_key`.
///
/// ## Example
///
/// ```
/// # use veccell::*;
/// let mut vec: VecCell<isize> = VecCell::new();
///
/// vec.push(30);
/// vec.push(0);
/// vec.push(20);
/// vec.push(10);
///
/// vec.sort_unstable_by_key(|a| -(*a));
///
/// assert_eq!(vec.borrow(0).unwrap(), 30);
/// assert_eq!(vec.borrow(1).unwrap(), 20);
/// assert_eq!(vec.borrow(2).unwrap(), 10);
/// assert_eq!(vec.borrow(3).unwrap(), 0);
/// ```
pub fn sort_unstable_by_key<K, F>(&mut self, mut f: F)
where
F: FnMut(&T) -> K,
K: Ord,
{
assert_eq!(
self.borrows.get(),
0,
"Sorting requires that no item is currently borrowed"
);
assert!(
self.mut_borrow.get().is_none(),
"Sorting requires that no item is currently (mutably) borrowed"
);
self.inner.sort_unstable_by(|a, b| {
// SAFETY: self is borrowed mutably and a and b are not itself changed.
let a = f(unsafe { &*a.get() });
let b = f(unsafe { &*b.get() });
a.cmp(&b)
});
}

/// Alternative to `get`, which skips all checks and returns a mutable reference.
/// Neither the `mut_borrow`, nor the `borrows` buffer will be updated or read,
/// so make sure that no exclusive reference to the element at `index` is made.
Expand All @@ -571,7 +696,11 @@ impl<T> VecCell<T> {
}

/// Constructs a `VecCell` from its raw parts.
pub unsafe fn from_raw_parts(inner: Vec<UnsafeCell<T>>, mut_borrow: Option<usize>, borrows: usize) -> Self {
pub unsafe fn from_raw_parts(
inner: Vec<UnsafeCell<T>>,
mut_borrow: Option<usize>,
borrows: usize,
) -> Self {
Self {
inner,
borrows: Cell::new(borrows),
Expand Down Expand Up @@ -599,12 +728,16 @@ impl<T: fmt::Debug> fmt::Debug for VecCell<T> {
f.debug_struct("VecCell")
.field("borrows", &self.borrows.get())
.field("mut_borrow", &self.mut_borrow.get())
.field("inner", &self.try_iter().map(|x| {
match x {
Some(y) => BorrowStatus::Ok(y),
None => BorrowStatus::Borrowed,
}
}).collect::<Box<[_]>>())
.field(
"inner",
&self
.try_iter()
.map(|x| match x {
Some(y) => BorrowStatus::Ok(y),
None => BorrowStatus::Borrowed,
})
.collect::<Box<[_]>>(),
)
.finish()
}
}
Expand All @@ -619,7 +752,7 @@ impl<'a, T: 'a> IntoIterator for &'a VecCell<T> {
fn into_iter(self) -> Self::IntoIter {
VecCellRefIter {
vec: self,
index: 0
index: 0,
}
}
}
Expand All @@ -629,20 +762,23 @@ impl<'a, T: 'a> IntoIterator for &'a VecCell<T> {
#[derive(Clone)]
pub struct VecCellRefIter<'a, T> {
vec: &'a VecCell<T>,
index: usize
index: usize,
}

impl<'a, T> Iterator for VecCellRefIter<'a, T> {
type Item = VecRef<'a, T>;

fn next(&mut self) -> Option<Self::Item> {
if self.index >= self.vec.len() {
return None
return None;
}

let res = match self.vec.borrow(self.index) {
Some(x) => x,
None => panic!("Error while borrowing immutably element {} of VecCell: already mutably borrowed", self.index),
None => panic!(
"Error while borrowing immutably element {} of VecCell: already mutably borrowed",
self.index
),
};
self.index += 1;

Expand Down Expand Up @@ -681,7 +817,7 @@ impl<T> IntoIterator for VecCell<T> {
/// Panics if a value is currently mutably borrowed
fn into_iter(self) -> Self::IntoIter {
VecCellIntoIter {
iter: self.inner.into_iter()
iter: self.inner.into_iter(),
}
}
}
Expand Down Expand Up @@ -718,7 +854,10 @@ impl<T: Clone> Clone for VecCell<T> {
/// Panics if a value is currently mutably borrowed
fn clone(&self) -> Self {
VecCell {
inner: self.into_iter().map(|x| UnsafeCell::new((*x).clone())).collect::<Vec<_>>(),
inner: self
.into_iter()
.map(|x| UnsafeCell::new((*x).clone()))
.collect::<Vec<_>>(),
mut_borrow: Cell::new(None),
borrows: Cell::new(0),
}
Expand All @@ -731,12 +870,12 @@ impl<T: PartialEq> PartialEq for VecCell<T> {
/// Panics if a value in `self` or `other` is currently mutably borrowed when it is encountered in the comparison.
fn eq(&self, other: &Self) -> bool {
if self.len() != other.len() {
return false
return false;
}

for (s, o) in self.iter().zip(other.iter()) {
if *s != *o {
return false
return false;
}
}

Expand All @@ -750,12 +889,12 @@ impl<T: PartialEq> PartialEq<Vec<T>> for VecCell<T> {
/// Panics if a value in `self` is currently mutably borrowed when it is encountered in the comparison.
fn eq(&self, other: &Vec<T>) -> bool {
if self.len() != other.len() {
return false
return false;
}

for (s, o) in self.iter().zip(other.iter()) {
if *s != *o {
return false
return false;
}
}

Expand All @@ -766,7 +905,10 @@ impl<T: PartialEq> PartialEq<Vec<T>> for VecCell<T> {
impl<T> From<Vec<T>> for VecCell<T> {
fn from(vec: Vec<T>) -> Self {
VecCell {
inner: vec.into_iter().map(|x| UnsafeCell::new(x)).collect::<Vec<_>>(),
inner: vec
.into_iter()
.map(|x| UnsafeCell::new(x))
.collect::<Vec<_>>(),
mut_borrow: Cell::new(None),
borrows: Cell::new(0),
}
Expand All @@ -783,9 +925,11 @@ impl<T> From<VecCell<T>> for Vec<T> {
impl<T: serde::Serialize> serde::Serialize for VecCell<T> {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: serde::Serializer
S: serde::Serializer,
{
let range = self.borrow_range(..).expect("Cannot borrow immutably VecCell: already borrowed mutably.");
let range = self
.borrow_range(..)
.expect("Cannot borrow immutably VecCell: already borrowed mutably.");
(*range).serialize(serializer)
}
}
Expand All @@ -794,7 +938,7 @@ impl<T: serde::Serialize> serde::Serialize for VecCell<T> {
impl<'de, T: serde::Deserialize<'de>> serde::Deserialize<'de> for VecCell<T> {
fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
where
D: serde::Deserializer<'de>
D: serde::Deserializer<'de>,
{
let vec: Vec<T> = Vec::deserialize(deserializer)?;
Ok(Self::from(vec))
Expand Down