use std::mem::{replace, swap};
use std::ops::{Range, RangeBounds};
use std::ptr::null;
use std::sync::atomic::{AtomicPtr, Ordering};
use archery::{SharedPointer, SharedPointerKind};
use crate::nodes::chunk::Chunk;
use crate::sync::Lock;
use crate::util::to_range;
use crate::vector::{
GenericVector, Iter, IterMut,
VectorInner::{Full, Inline, Single},
RRB,
};
fn check_indices<const N: usize>(len: usize, indices: &[usize; N]) -> Option<()> {
let mut seen = [None; N];
for idx in indices {
if *idx > len || seen.contains(&Some(*idx)) {
return None;
}
let empty = seen.iter_mut().find(|a| a.is_none()).unwrap();
*empty = Some(*idx);
}
Some(())
}
pub enum Focus<'a, A, P: SharedPointerKind> {
#[doc(hidden)]
Single(&'a [A]),
#[doc(hidden)]
Full(TreeFocus<A, P>),
}
impl<'a, A, P: SharedPointerKind> Focus<'a, A, P>
where
A: 'a,
{
pub fn new(vector: &'a GenericVector<A, P>) -> Self {
match &vector.vector {
Inline(chunk) => Focus::Single(chunk),
Single(chunk) => Focus::Single(chunk),
Full(tree) => Focus::Full(TreeFocus::new(tree)),
}
}
pub fn len(&self) -> usize {
match self {
Focus::Single(chunk) => chunk.len(),
Focus::Full(tree) => tree.len(),
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
pub fn get(&mut self, index: usize) -> Option<&A> {
match self {
Focus::Single(chunk) => chunk.get(index),
Focus::Full(tree) => tree.get(index),
}
}
pub fn index(&mut self, index: usize) -> &A {
self.get(index).expect("index out of bounds")
}
pub fn chunk_at(&mut self, index: usize) -> (Range<usize>, &[A]) {
let len = self.len();
if index >= len {
panic!("vector::Focus::chunk_at: index out of bounds");
}
match self {
Focus::Single(chunk) => (0..len, chunk),
Focus::Full(tree) => tree.get_chunk(index),
}
}
#[must_use]
pub fn narrow<R>(self, range: R) -> Self
where
R: RangeBounds<usize>,
{
let r = to_range(&range, self.len());
if r.start > r.end || r.end > self.len() {
panic!("vector::Focus::narrow: range out of bounds");
}
match self {
Focus::Single(chunk) => Focus::Single(&chunk[r]),
Focus::Full(tree) => Focus::Full(tree.narrow(r)),
}
}
pub fn split_at(self, index: usize) -> (Self, Self) {
if index > self.len() {
panic!("vector::Focus::split_at: index out of bounds");
}
match self {
Focus::Single(chunk) => {
let (left, right) = chunk.split_at(index);
(Focus::Single(left), Focus::Single(right))
}
Focus::Full(tree) => {
let (left, right) = tree.split_at(index);
(Focus::Full(left), Focus::Full(right))
}
}
}
}
impl<'a, A, P: SharedPointerKind + 'a> IntoIterator for Focus<'a, A, P>
where
A: Clone + 'a,
{
type Item = &'a A;
type IntoIter = Iter<'a, A, P>;
fn into_iter(self) -> Self::IntoIter {
Iter::from_focus(self)
}
}
impl<'a, A, P: SharedPointerKind> Clone for Focus<'a, A, P>
where
A: Clone + 'a,
{
fn clone(&self) -> Self {
match self {
Focus::Single(chunk) => Focus::Single(chunk),
Focus::Full(tree) => Focus::Full(tree.clone()),
}
}
}
pub struct TreeFocus<A, P: SharedPointerKind> {
tree: RRB<A, P>,
view: Range<usize>,
middle_range: Range<usize>,
target_range: Range<usize>,
target_ptr: *const Chunk<A>,
}
impl<A, P: SharedPointerKind> Clone for TreeFocus<A, P> {
fn clone(&self) -> Self {
let tree = self.tree.clone();
TreeFocus {
view: self.view.clone(),
middle_range: self.middle_range.clone(),
target_range: 0..0,
target_ptr: null(),
tree,
}
}
}
unsafe impl<A: Send, P: SharedPointerKind + Send> Send for TreeFocus<A, P> {}
unsafe impl<A: Sync, P: SharedPointerKind + Sync> Sync for TreeFocus<A, P> {}
#[inline]
fn contains<A: Ord>(range: &Range<A>, index: &A) -> bool {
*index >= range.start && *index < range.end
}
impl<A, P: SharedPointerKind> TreeFocus<A, P> {
fn new(tree: &RRB<A, P>) -> Self {
let middle_start = tree.outer_f.len() + tree.inner_f.len();
let middle_end = middle_start + tree.middle.len();
TreeFocus {
tree: tree.clone(),
view: 0..tree.length,
middle_range: middle_start..middle_end,
target_range: 0..0,
target_ptr: null(),
}
}
fn len(&self) -> usize {
self.view.end - self.view.start
}
fn narrow(self, mut view: Range<usize>) -> Self {
view.start += self.view.start;
view.end += self.view.start;
TreeFocus {
view,
middle_range: self.middle_range.clone(),
target_range: 0..0,
target_ptr: null(),
tree: self.tree,
}
}
fn split_at(self, index: usize) -> (Self, Self) {
let len = self.len();
let left = self.clone().narrow(0..index);
let right = self.narrow(index..len);
(left, right)
}
fn physical_index(&self, index: usize) -> usize {
debug_assert!(index < self.view.end);
self.view.start + index
}
fn logical_range(&self, range: &Range<usize>) -> Range<usize> {
(range.start - self.view.start)..(range.end - self.view.start)
}
fn set_focus(&mut self, index: usize) {
if index < self.middle_range.start {
let outer_len = self.tree.outer_f.len();
if index < outer_len {
self.target_range = 0..outer_len;
self.target_ptr = &*self.tree.outer_f;
} else {
self.target_range = outer_len..self.middle_range.start;
self.target_ptr = &*self.tree.inner_f;
}
} else if index >= self.middle_range.end {
let outer_start = self.middle_range.end + self.tree.inner_b.len();
if index < outer_start {
self.target_range = self.middle_range.end..outer_start;
self.target_ptr = &*self.tree.inner_b;
} else {
self.target_range = outer_start..self.tree.length;
self.target_ptr = &*self.tree.outer_b;
}
} else {
let tree_index = index - self.middle_range.start;
let (range, ptr) = self
.tree
.middle
.lookup_chunk(self.tree.middle_level, 0, tree_index);
self.target_range =
(range.start + self.middle_range.start)..(range.end + self.middle_range.start);
self.target_ptr = ptr;
}
}
fn get_focus(&self) -> &Chunk<A> {
unsafe { &*self.target_ptr }
}
pub fn get(&mut self, index: usize) -> Option<&A> {
if index >= self.len() {
return None;
}
let phys_index = self.physical_index(index);
if !contains(&self.target_range, &phys_index) {
self.set_focus(phys_index);
}
let target_phys_index = phys_index - self.target_range.start;
Some(&self.get_focus()[target_phys_index])
}
pub fn get_chunk(&mut self, index: usize) -> (Range<usize>, &[A]) {
let phys_index = self.physical_index(index);
if !contains(&self.target_range, &phys_index) {
self.set_focus(phys_index);
}
let mut slice: &[A] = self.get_focus();
let mut left = 0;
let mut right = 0;
if self.target_range.start < self.view.start {
left = self.view.start - self.target_range.start;
}
if self.target_range.end > self.view.end {
right = self.target_range.end - self.view.end;
}
slice = &slice[left..(slice.len() - right)];
let phys_range = (self.target_range.start + left)..(self.target_range.end - right);
(self.logical_range(&phys_range), slice)
}
}
pub enum FocusMut<'a, A, P: SharedPointerKind> {
#[doc(hidden)]
Single(&'a mut [A]),
#[doc(hidden)]
Full(TreeFocusMut<'a, A, P>),
}
impl<'a, A, P: SharedPointerKind> FocusMut<'a, A, P>
where
A: 'a,
{
pub fn len(&self) -> usize {
match self {
FocusMut::Single(chunk) => chunk.len(),
FocusMut::Full(tree) => tree.len(),
}
}
pub fn is_empty(&self) -> bool {
self.len() == 0
}
#[must_use]
pub fn narrow<R>(self, range: R) -> Self
where
R: RangeBounds<usize>,
{
let r = to_range(&range, self.len());
if r.start > r.end || r.start > self.len() {
panic!("vector::FocusMut::narrow: range out of bounds");
}
match self {
FocusMut::Single(chunk) => FocusMut::Single(&mut chunk[r]),
FocusMut::Full(tree) => FocusMut::Full(tree.narrow(r)),
}
}
#[allow(clippy::redundant_clone)]
pub fn split_at(self, index: usize) -> (Self, Self) {
if index > self.len() {
panic!("vector::FocusMut::split_at: index out of bounds");
}
match self {
FocusMut::Single(chunk) => {
let (left, right) = chunk.split_at_mut(index);
(FocusMut::Single(left), FocusMut::Single(right))
}
FocusMut::Full(tree) => {
let (left, right) = tree.split_at(index);
(FocusMut::Full(left), FocusMut::Full(right))
}
}
}
pub fn unmut(self) -> Focus<'a, A, P> {
match self {
FocusMut::Single(chunk) => Focus::Single(chunk),
FocusMut::Full(mut tree) => Focus::Full(TreeFocus {
tree: {
let t = tree.tree.lock().unwrap();
(*t).clone()
},
view: tree.view.clone(),
middle_range: tree.middle_range.clone(),
target_range: 0..0,
target_ptr: null(),
}),
}
}
}
impl<'a, A, P: SharedPointerKind> FocusMut<'a, A, P>
where
A: Clone + 'a,
{
pub fn new(vector: &'a mut GenericVector<A, P>) -> Self {
match &mut vector.vector {
Inline(chunk) => FocusMut::Single(chunk),
Single(chunk) => FocusMut::Single(SharedPointer::make_mut(chunk).as_mut_slice()),
Full(tree) => FocusMut::Full(TreeFocusMut::new(tree)),
}
}
pub fn get(&mut self, index: usize) -> Option<&A> {
self.get_mut(index).map(|r| &*r)
}
pub fn get_mut(&mut self, index: usize) -> Option<&mut A> {
match self {
FocusMut::Single(chunk) => chunk.get_mut(index),
FocusMut::Full(tree) => tree.get(index),
}
}
fn get_many_mut<const N: usize>(&mut self, indices: [usize; N]) -> Option<[&mut A; N]> {
check_indices(self.len(), &indices)?;
match self {
FocusMut::Single(chunk) => {
let chunk: *mut A = (*chunk).as_mut_ptr();
Some(indices.map(|index| {
unsafe { &mut *chunk.add(index) }
}))
}
FocusMut::Full(tree) => tree.get_many(indices),
}
}
pub fn index(&mut self, index: usize) -> &A {
&*self.index_mut(index)
}
#[allow(clippy::should_implement_trait)] pub fn index_mut(&mut self, index: usize) -> &mut A {
self.get_mut(index).expect("index out of bounds")
}
fn index_many_mut<const N: usize>(&mut self, indices: [usize; N]) -> [&mut A; N] {
self.get_many_mut(indices)
.expect("index out of bounds or overlapping")
}
pub fn set(&mut self, index: usize, value: A) -> Option<A> {
self.get_mut(index).map(|pos| replace(pos, value))
}
pub fn swap(&mut self, a: usize, b: usize) {
if a == b {
return;
}
self.pair(a, b, |left, right| swap(left, right));
}
pub fn pair<F, B>(&mut self, a: usize, b: usize, mut f: F) -> B
where
F: FnMut(&mut A, &mut A) -> B,
{
if a == b {
panic!("vector::FocusMut::pair: indices cannot be equal!");
}
let [pa, pb] = self.index_many_mut([a, b]);
f(pa, pb)
}
pub fn triplet<F, B>(&mut self, a: usize, b: usize, c: usize, mut f: F) -> B
where
F: FnMut(&mut A, &mut A, &mut A) -> B,
{
if a == b || b == c || a == c {
panic!("vector::FocusMut::triplet: indices cannot be equal!");
}
let [pa, pb, pc] = self.index_many_mut([a, b, c]);
f(pa, pb, pc)
}
pub fn chunk_at(&mut self, index: usize) -> (Range<usize>, &mut [A]) {
let len = self.len();
if index >= len {
panic!("vector::FocusMut::chunk_at: index out of bounds");
}
match self {
FocusMut::Single(chunk) => (0..len, chunk),
FocusMut::Full(tree) => {
let (range, chunk) = tree.get_chunk(index);
(range, chunk)
}
}
}
}
impl<'a, A, P: SharedPointerKind> IntoIterator for FocusMut<'a, A, P>
where
A: Clone + 'a,
{
type Item = &'a mut A;
type IntoIter = IterMut<'a, A, P>;
fn into_iter(self) -> Self::IntoIter {
IterMut::from_focus(self)
}
}
impl<'a, A, P: SharedPointerKind> From<FocusMut<'a, A, P>> for Focus<'a, A, P>
where
A: Clone + 'a,
{
fn from(f: FocusMut<'a, A, P>) -> Focus<'a, A, P> {
f.unmut()
}
}
pub struct TreeFocusMut<'a, A, P: SharedPointerKind> {
tree: Lock<&'a mut RRB<A, P>>,
view: Range<usize>,
middle_range: Range<usize>,
target_range: Range<usize>,
target_ptr: AtomicPtr<Chunk<A>>,
}
impl<'a, A, P: SharedPointerKind> TreeFocusMut<'a, A, P>
where
A: 'a,
{
fn new(tree: &'a mut RRB<A, P>) -> Self {
let middle_start = tree.outer_f.len() + tree.inner_f.len();
let middle_end = middle_start + tree.middle.len();
TreeFocusMut {
view: 0..tree.length,
tree: Lock::new(tree),
middle_range: middle_start..middle_end,
target_range: 0..0,
target_ptr: AtomicPtr::default(),
}
}
fn len(&self) -> usize {
self.view.end - self.view.start
}
fn narrow(self, mut view: Range<usize>) -> Self {
view.start += self.view.start;
view.end += self.view.start;
TreeFocusMut {
view,
middle_range: self.middle_range.clone(),
target_range: 0..0,
target_ptr: AtomicPtr::default(),
tree: self.tree,
}
}
fn split_at(self, index: usize) -> (Self, Self) {
let len = self.len();
debug_assert!(index <= len);
let left = TreeFocusMut {
view: self.view.start..(self.view.start + index),
middle_range: self.middle_range.clone(),
target_range: 0..0,
target_ptr: AtomicPtr::default(),
tree: self.tree.clone(),
};
let right = TreeFocusMut {
view: (self.view.start + index)..(self.view.start + len),
middle_range: self.middle_range.clone(),
target_range: 0..0,
target_ptr: AtomicPtr::default(),
tree: self.tree,
};
(left, right)
}
fn physical_index(&self, index: usize) -> usize {
debug_assert!(index < self.view.end);
self.view.start + index
}
fn logical_range(&self, range: &Range<usize>) -> Range<usize> {
(range.start - self.view.start)..(range.end - self.view.start)
}
fn get_focus(&mut self) -> &mut Chunk<A> {
unsafe { &mut *self.target_ptr.load(Ordering::Relaxed) }
}
fn get_focus_ptr(&mut self) -> *mut Chunk<A> {
self.target_ptr.load(Ordering::Relaxed)
}
}
impl<'a, A, P: SharedPointerKind> TreeFocusMut<'a, A, P>
where
A: Clone + 'a,
{
fn set_focus(&mut self, index: usize) {
let mut tree = self
.tree
.lock()
.expect("imbl::vector::Focus::set_focus: unable to acquire exclusive lock on Vector");
if index < self.middle_range.start {
let outer_len = tree.outer_f.len();
if index < outer_len {
self.target_range = 0..outer_len;
self.target_ptr.store(
SharedPointer::make_mut(&mut tree.outer_f),
Ordering::Relaxed,
);
} else {
self.target_range = outer_len..self.middle_range.start;
self.target_ptr.store(
SharedPointer::make_mut(&mut tree.inner_f),
Ordering::Relaxed,
);
}
} else if index >= self.middle_range.end {
let outer_start = self.middle_range.end + tree.inner_b.len();
if index < outer_start {
self.target_range = self.middle_range.end..outer_start;
self.target_ptr.store(
SharedPointer::make_mut(&mut tree.inner_b),
Ordering::Relaxed,
);
} else {
self.target_range = outer_start..tree.length;
self.target_ptr.store(
SharedPointer::make_mut(&mut tree.outer_b),
Ordering::Relaxed,
);
}
} else {
let tree_index = index - self.middle_range.start;
let level = tree.middle_level;
let middle = SharedPointer::make_mut(&mut tree.middle);
let (range, ptr) = middle.lookup_chunk_mut(level, 0, tree_index);
self.target_range =
(range.start + self.middle_range.start)..(range.end + self.middle_range.start);
self.target_ptr.store(ptr, Ordering::Relaxed);
}
}
pub fn get(&mut self, index: usize) -> Option<&mut A> {
if index >= self.len() {
return None;
}
let phys_index = self.physical_index(index);
if !contains(&self.target_range, &phys_index) {
self.set_focus(phys_index);
}
let target_phys_index = phys_index - self.target_range.start;
Some(&mut self.get_focus()[target_phys_index])
}
fn get_many<const N: usize>(&mut self, indices: [usize; N]) -> Option<[&mut A; N]> {
check_indices(self.len(), &indices)?;
Some(indices.map(|phys_idx| {
if !contains(&self.target_range, &phys_idx) {
self.set_focus(phys_idx);
}
let target_idx = phys_idx - self.target_range.start;
unsafe {
let chunk = self.get_focus_ptr();
let ptr: *mut [A] = Chunk::as_mut_slice_ptr(chunk);
&mut *ptr.cast::<A>().add(target_idx)
}
}))
}
pub fn get_chunk(&mut self, index: usize) -> (Range<usize>, &mut [A]) {
let phys_index = self.physical_index(index);
if !contains(&self.target_range, &phys_index) {
self.set_focus(phys_index);
}
let mut left = 0;
let mut right = 0;
if self.target_range.start < self.view.start {
left = self.view.start - self.target_range.start;
}
if self.target_range.end > self.view.end {
right = self.target_range.end - self.view.end;
}
let phys_range = (self.target_range.start + left)..(self.target_range.end - right);
let log_range = self.logical_range(&phys_range);
let slice_len = self.get_focus().len();
let slice = &mut self.get_focus().as_mut_slice()[left..(slice_len - right)];
(log_range, slice)
}
}