use std::{
cmp::{Eq, PartialEq},
fmt,
hash::{Hash, Hasher},
iter::FusedIterator,
mem,
ops::{Deref, DerefMut, Index, IndexMut},
ptr,
slice::{self, SliceIndex},
sync::Arc,
};
pub mod error;
use crate::error::{CantMerge, WouldAlloc, WouldMove};
#[cfg(feature = "serde")]
mod serde_impl;
pub trait ShardExt {
type Shard;
fn split_inplace_at(self, at: usize) -> (Self::Shard, Self::Shard);
}
struct VecDropper<T> {
ptr: *mut T,
capacity: usize,
}
impl<T> Drop for VecDropper<T> {
fn drop(&mut self) {
unsafe {
mem::drop(Vec::from_raw_parts(self.ptr, 0, self.capacity));
}
}
}
pub struct VecShard<T> {
dropper: Arc<VecDropper<T>>,
data: *mut T,
len: usize,
}
unsafe impl<T: Send> Send for VecShard<T> {}
unsafe impl<T: Sync> Sync for VecShard<T> {}
impl<T> VecShard<T> {
fn into_raw_parts(self) -> (Arc<VecDropper<T>>, *mut T, usize) {
let dropper = unsafe { ptr::read(&self.dropper as *const Arc<VecDropper<T>>) };
let data = self.data;
let len = self.len;
mem::forget(self);
(dropper, data, len)
}
pub fn merge_inplace(left: Self, right: Self) -> Result<Self, CantMerge<T, WouldMove>> {
use WouldMove::*;
if !Arc::ptr_eq(&left.dropper, &right.dropper) {
Err(CantMerge {
reason: DifferentAllocations,
left,
right,
})
} else if unsafe { left.data.add(left.len) } == right.data {
let (ldropper, ldata, llen) = left.into_raw_parts();
let (rdropper, _, rlen) = right.into_raw_parts();
std::mem::drop(rdropper);
Ok(VecShard {
dropper: ldropper,
data: ldata,
len: llen + rlen,
})
} else if unsafe { right.data.add(right.len) } == left.data {
Err(CantMerge {
left,
right,
reason: WrongOrder,
})
} else {
Err(CantMerge {
reason: NotAdjacent,
left,
right,
})
}
}
pub fn merge_noalloc(left: Self, right: Self) -> Result<Self, CantMerge<T, WouldAlloc>> {
use WouldMove::*;
let cant_merge = match Self::merge_inplace(left, right) {
Ok(shard) => return Ok(shard),
Err(err) => err,
};
if cant_merge.reason == DifferentAllocations {
return Err(CantMerge {
left: cant_merge.left,
right: cant_merge.right,
reason: WouldAlloc::DifferentAllocations,
});
}
let (ldropper, ldata, llen) = cant_merge.left.into_raw_parts();
let (rdropper, rdata, rlen) = cant_merge.right.into_raw_parts();
if cant_merge.reason == WrongOrder {
unsafe { slice::from_raw_parts_mut(rdata, llen + rlen).rotate_left(rlen) };
Ok(VecShard {
dropper: ldropper,
data: rdata,
len: llen + rlen,
})
} else if cant_merge.reason == NotAdjacent && Arc::strong_count(&ldropper) == 2 {
let new_data = unsafe {
if rdata < ldata {
if llen < rlen {
ptr::swap_nonoverlapping(rdata, ldata, llen);
ptr::copy(ldata, rdata.add(rlen), llen);
slice::from_raw_parts_mut(rdata.add(llen), rlen).rotate_left(rlen - llen);
} else {
ptr::swap_nonoverlapping(rdata, ldata, rlen);
slice::from_raw_parts_mut(ldata, llen).rotate_left(rlen);
ptr::copy(ldata, rdata.add(rlen), llen);
};
rdata
} else {
ptr::copy(rdata, ldata.add(llen), rlen);
ldata
}
};
Ok(VecShard {
data: new_data,
len: llen + rlen,
dropper: ldropper,
})
} else {
Err(CantMerge {
reason: WouldAlloc::OtherShardsLeft,
left: VecShard {
dropper: ldropper,
data: ldata,
len: llen,
},
right: VecShard {
dropper: rdropper,
data: rdata,
len: rlen,
},
})
}
}
pub fn merge(left: Self, right: Self) -> Self {
Self::merge_noalloc(left, right).unwrap_or_else(|err| {
let (_ldropper, ldata, llen) = err.left.into_raw_parts();
let (_rdropper, rdata, rlen) = err.right.into_raw_parts();
let mut vec = Vec::with_capacity(llen + rlen);
unsafe {
ptr::copy(ldata, vec.as_mut_ptr(), llen);
ptr::copy(rdata, vec.as_mut_ptr().add(llen), rlen);
vec.set_len(llen + rlen);
}
Self::from(vec)
})
}
}
impl<T> ShardExt for VecShard<T> {
type Shard = VecShard<T>;
fn split_inplace_at(mut self, at: usize) -> (Self::Shard, Self::Shard) {
assert!(at <= self.len);
let right = VecShard {
dropper: self.dropper.clone(),
data: unsafe { self.data.add(at) },
len: self.len - at,
};
self.len = at;
(self, right)
}
}
impl<T> Drop for VecShard<T> {
fn drop(&mut self) {
for o in 0..self.len {
unsafe { ptr::drop_in_place(self.data.add(o)) };
}
}
}
impl<T> Deref for VecShard<T> {
type Target = [T];
fn deref(&self) -> &[T] {
unsafe { slice::from_raw_parts(self.data, self.len) }
}
}
impl<T> DerefMut for VecShard<T> {
fn deref_mut(&mut self) -> &mut [T] {
unsafe { slice::from_raw_parts_mut(self.data, self.len) }
}
}
impl<T, I: SliceIndex<[T]>> Index<I> for VecShard<T> {
type Output = <I as slice::SliceIndex<[T]>>::Output;
fn index(&self, idx: I) -> &Self::Output {
&((**self)[idx])
}
}
impl<T, I: SliceIndex<[T]>> IndexMut<I> for VecShard<T> {
fn index_mut(&mut self, idx: I) -> &mut Self::Output {
&mut ((**self)[idx])
}
}
impl<T: PartialEq> PartialEq for VecShard<T> {
fn eq(&self, rhs: &Self) -> bool {
**self == **rhs
}
}
impl<T: Eq> Eq for VecShard<T> {}
impl<T> Iterator for VecShard<T> {
type Item = T;
fn next(&mut self) -> Option<T> {
if self.len > 0 {
let res = unsafe { self.data.read() };
self.len -= 1;
self.data = unsafe { self.data.add(1) };
Some(res)
} else {
None
}
}
fn size_hint(&self) -> (usize, Option<usize>) {
(self.len, Some(self.len))
}
}
impl<T> ExactSizeIterator for VecShard<T> {
fn len(&self) -> usize {
self.len
}
}
impl<T> DoubleEndedIterator for VecShard<T> {
fn next_back(&mut self) -> Option<T> {
if self.len > 0 {
self.len -= 1;
Some(unsafe { self.data.add(self.len).read() })
} else {
None
}
}
}
impl<T> FusedIterator for VecShard<T> {}
impl<T: Hash> Hash for VecShard<T> {
fn hash<H: Hasher>(&self, state: &mut H) {
Hash::hash(&**self, state)
}
}
impl<T> From<Vec<T>> for VecShard<T> {
fn from(mut v: Vec<T>) -> Self {
let res = VecShard {
dropper: Arc::new(VecDropper {
ptr: v.as_mut_ptr(),
capacity: v.capacity(),
}),
data: v.as_mut_ptr(),
len: v.len(),
};
mem::forget(v);
res
}
}
impl<T> Into<Vec<T>> for VecShard<T> {
fn into(self) -> Vec<T> {
let (dropper, data, len) = self.into_raw_parts();
if let Ok(dropper) = Arc::try_unwrap(dropper) {
if data != dropper.ptr {
unsafe { ptr::copy(data, dropper.ptr, len) };
}
let v = unsafe { Vec::from_raw_parts(dropper.ptr, len, dropper.capacity) };
mem::forget(dropper);
v
} else {
let mut v = Vec::with_capacity(len);
unsafe {
ptr::copy_nonoverlapping(data, v.as_mut_ptr(), len);
v.set_len(len);
};
v
}
}
}
impl<T: Clone> Clone for VecShard<T> {
fn clone(&self) -> VecShard<T> {
let mut vec = Vec::with_capacity(self.len);
vec.extend_from_slice(unsafe { slice::from_raw_parts(self.data, self.len) });
VecShard::from(vec)
}
}
impl<T: fmt::Debug> fmt::Debug for VecShard<T> {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{:?}", &**self)
}
}
impl<T> ShardExt for Vec<T> {
type Shard = VecShard<T>;
fn split_inplace_at(self, at: usize) -> (Self::Shard, Self::Shard) {
VecShard::from(self).split_inplace_at(at)
}
}