use core::{marker::PhantomData, ptr::NonNull};
use crate::{rot_left, rot_right};
#[derive(Debug, PartialEq)]
pub(crate) struct Bricks<const L: usize> {
idx_buf: [usize; L],
local_editable_end: usize, remote_editable_end: usize, history_end: usize, }
pub struct LineIter<'a, const L: usize, I> {
bricks: &'a [usize],
collection: &'a [I],
}
pub struct LineIterMut<'a, 'b, const L: usize, I> {
bricks: &'a [usize],
col_ptr: NonNull<[I]>,
_cpd: PhantomData<&'b mut [I]>,
}
impl<'a, const L: usize, I> Iterator for LineIter<'a, L, I> {
type Item = &'a I;
fn next(&mut self) -> Option<Self::Item> {
let (now, remain) = self.bricks.split_first()?;
self.bricks = remain;
self.collection.get(*now)
}
}
impl<'a, const L: usize, I> DoubleEndedIterator for LineIter<'a, L, I> {
fn next_back(&mut self) -> Option<Self::Item> {
let (now, remain) = self.bricks.split_last()?;
self.bricks = remain;
self.collection.get(*now)
}
}
impl<'a, 'b, const L: usize, I> Iterator for LineIterMut<'a, 'b, L, I> {
type Item = &'b mut I;
fn next(&mut self) -> Option<Self::Item> {
let (now, remain) = self.bricks.split_first()?;
self.bricks = remain;
unsafe { Some(&mut *self.col_ptr.as_ptr().cast::<I>().add(*now)) }
}
}
impl<'a, 'b, const L: usize, I> DoubleEndedIterator for LineIterMut<'a, 'b, L, I> {
fn next_back(&mut self) -> Option<Self::Item> {
let (now, remain) = self.bricks.split_last()?;
self.bricks = remain;
unsafe { Some(&mut *self.col_ptr.as_ptr().cast::<I>().add(*now)) }
}
}
impl<const L: usize> Bricks<L> {
pub fn new() -> Self {
let mut idx_buf = [0; L];
idx_buf.iter_mut().enumerate().for_each(|(i, v)| *v = i);
Self {
idx_buf: idx_buf,
local_editable_end: 0,
remote_editable_end: 0,
history_end: 0,
}
}
pub fn iter_local_editable<'a, I>(&'a self, t: &'a [I]) -> LineIter<'a, L, I> {
LineIter {
bricks: &self.idx_buf[0..self.local_editable_end],
collection: t,
}
}
pub fn iter_remote_editable<'a, I>(&'a self, t: &'a [I]) -> LineIter<'a, L, I> {
LineIter {
bricks: &self.idx_buf[self.local_editable_end..self.remote_editable_end],
collection: t,
}
}
pub fn iter_local_editable_mut<'a, 'b, I>(
&'a self,
t: &'b mut [I],
) -> LineIterMut<'a, 'b, L, I> {
LineIterMut {
bricks: &self.idx_buf[0..self.local_editable_end],
col_ptr: NonNull::from(t),
_cpd: PhantomData,
}
}
pub fn iter_remote_editable_mut<'a, 'b, I>(
&'a self,
t: &'b mut [I],
) -> LineIterMut<'a, 'b, L, I> {
LineIterMut {
bricks: &self.idx_buf[self.local_editable_end..self.remote_editable_end],
col_ptr: NonNull::from(t),
_cpd: PhantomData,
}
}
pub fn iter_history<'a, I>(&'a self, t: &'a [I]) -> LineIter<'a, L, I> {
LineIter {
bricks: &self.idx_buf[self.remote_editable_end..self.history_end],
collection: t,
}
}
pub fn pop_local_editable_front(&mut self) {
if self.local_editable_end == 0 {
return;
}
rot_left(&mut self.idx_buf[..self.history_end]);
self.local_editable_end -= 1;
self.remote_editable_end -= 1;
self.history_end -= 1;
}
pub fn pop_remote_editable_front(&mut self) {
if self.remote_editable_end == self.local_editable_end {
return;
}
rot_left(&mut self.idx_buf[self.local_editable_end..self.history_end]);
self.remote_editable_end -= 1;
self.history_end -= 1;
}
pub fn local_editable_front(&self) -> Option<usize> {
if self.local_editable_end == 0 {
None
} else {
Some(self.idx_buf[0])
}
}
pub fn remote_editable_front(&self) -> Option<usize> {
if self.remote_editable_end == self.local_editable_end {
None
} else {
Some(self.idx_buf[self.local_editable_end])
}
}
pub fn insert_local_editable_front(&mut self) -> Result<usize, ()> {
if self.local_editable_end == L {
return Err(());
}
let end = self.history_end.wrapping_add(1).min(L);
rot_right(&mut self.idx_buf[..end]);
self.local_editable_end = self.local_editable_end.wrapping_add(1).min(L);
self.remote_editable_end = self.remote_editable_end.wrapping_add(1).min(L);
self.history_end = self.history_end.wrapping_add(1).min(L);
Ok(self.idx_buf[0])
}
pub fn insert_remote_editable_front(&mut self) -> Result<usize, ()> {
if self.remote_editable_end == L {
return Err(());
}
let end = self.history_end.wrapping_add(1).min(L);
rot_right(&mut self.idx_buf[self.local_editable_end..end]);
self.remote_editable_end = self.remote_editable_end.wrapping_add(1).min(L);
self.history_end = self.history_end.wrapping_add(1).min(L);
Ok(self.idx_buf[self.local_editable_end])
}
pub fn submit_local_editable(&mut self) {
let range = &mut self.idx_buf[..self.remote_editable_end];
for _ in 0..(self.remote_editable_end - self.local_editable_end) {
rot_right(range);
}
self.remote_editable_end -= self.local_editable_end;
self.local_editable_end = 0;
}
pub fn submit_remote_editable(&mut self) {
self.remote_editable_end = self.local_editable_end;
}
}
#[cfg(test)]
pub mod brick_tests {
use super::Bricks;
#[test]
fn smoke() {
let mut brick = Bricks::<8>::new();
println!("{:?}", brick);
for i in 0..8 {
let x = brick.insert_local_editable_front().unwrap();
println!("{:?}", brick);
assert_eq!(x, i);
}
println!("{:?}", brick);
brick.insert_local_editable_front().unwrap_err();
assert_eq!(
brick,
Bricks {
idx_buf: [7, 6, 5, 4, 3, 2, 1, 0],
local_editable_end: 8,
remote_editable_end: 8,
history_end: 8,
}
);
println!("=====");
let mut brick = Bricks::<8>::new();
for i in 0..4 {
let x = brick.insert_local_editable_front().unwrap();
println!("{:?}", brick);
assert_eq!(x, i);
}
assert_eq!(
brick,
Bricks {
idx_buf: [3, 2, 1, 0, 4, 5, 6, 7],
local_editable_end: 4,
remote_editable_end: 4,
history_end: 4,
}
);
println!("-----");
for i in 4..8 {
let x = brick.insert_remote_editable_front().unwrap();
println!("{:?}", brick);
assert_eq!(x, i);
}
assert_eq!(
brick,
Bricks {
idx_buf: [3, 2, 1, 0, 7, 6, 5, 4],
local_editable_end: 4,
remote_editable_end: 8,
history_end: 8,
}
);
println!("{:?}", brick);
println!("=====");
let mut brick = Bricks::<8>::new();
for i in 0..3 {
let x = brick.insert_local_editable_front().unwrap();
println!("{:?}", brick);
assert_eq!(x, i);
}
for i in 3..5 {
let x = brick.insert_remote_editable_front().unwrap();
println!("{:?}", brick);
assert_eq!(x, i);
}
println!("{:?}", brick);
assert_eq!(
brick,
Bricks {
idx_buf: [2, 1, 0, 4, 3, 5, 6, 7],
local_editable_end: 3,
remote_editable_end: 5,
history_end: 5,
}
);
println!("-----");
brick.submit_local_editable();
println!("{:?}", brick);
assert_eq!(
brick,
Bricks {
idx_buf: [4, 3, 2, 1, 0, 5, 6, 7],
local_editable_end: 0,
remote_editable_end: 2,
history_end: 5,
}
);
println!("-----");
brick.submit_remote_editable();
println!("{:?}", brick);
assert_eq!(
brick,
Bricks {
idx_buf: [4, 3, 2, 1, 0, 5, 6, 7],
local_editable_end: 0,
remote_editable_end: 0,
history_end: 5,
}
);
println!("=====");
for i in 5..8 {
let x = brick.insert_local_editable_front().unwrap();
println!("{:?}", brick);
assert_eq!(x, i);
}
println!("{:?}", brick);
assert_eq!(
brick,
Bricks {
idx_buf: [7, 6, 5, 4, 3, 2, 1, 0],
local_editable_end: 3,
remote_editable_end: 3,
history_end: 8,
}
);
println!("-----");
for i in 0..2 {
let x = brick.insert_remote_editable_front().unwrap();
println!("{:?}", brick);
assert_eq!(x, i);
}
println!("{:?}", brick);
assert_eq!(
brick,
Bricks {
idx_buf: [7, 6, 5, 1, 0, 4, 3, 2],
local_editable_end: 3,
remote_editable_end: 5,
history_end: 8,
}
);
let mut buf = [10, 20, 30, 40, 50, 60, 70, 80];
assert_eq!(
brick
.iter_local_editable(&buf)
.copied()
.collect::<Vec<_>>()
.as_slice(),
&[80, 70, 60],
);
assert_eq!(
brick
.iter_local_editable_mut(&mut buf)
.map(|c| *c)
.collect::<Vec<_>>()
.as_slice(),
&[80, 70, 60],
);
assert_eq!(
brick
.iter_remote_editable(&buf)
.copied()
.collect::<Vec<_>>()
.as_slice(),
&[20, 10],
);
assert_eq!(
brick
.iter_remote_editable_mut(&mut buf)
.map(|c| *c)
.collect::<Vec<_>>()
.as_slice(),
&[20, 10],
);
assert_eq!(
brick
.iter_history(&buf)
.copied()
.collect::<Vec<_>>()
.as_slice(),
&[50, 40, 30],
);
println!("-----");
for i in 2..5 {
let x = brick.insert_local_editable_front().unwrap();
println!("{:?}", brick);
assert_eq!(x, i);
}
println!("{:?}", brick);
assert_eq!(
brick,
Bricks {
idx_buf: [4, 3, 2, 7, 6, 5, 1, 0],
local_editable_end: 6,
remote_editable_end: 8,
history_end: 8,
}
);
brick.insert_remote_editable_front().unwrap_err();
assert_eq!(brick.insert_local_editable_front().unwrap(), 0);
}
}