use std::borrow::Borrow;
use std::fmt::{Debug, Display};
use std::ops::Deref;
use crate::rope::Measurable;
use self::inner::LeafSmallVec;
#[derive(Clone, Default)]
#[repr(C)]
pub(crate) struct LeafSlice<M>(inner::LeafSmallVec<M>)
where
M: Measurable;
impl<M> LeafSlice<M>
where
M: Measurable,
{
pub fn from_slice(value: &[M]) -> Self {
Self(LeafSmallVec::from_slice(value))
}
pub fn insert_slice(&mut self, index: usize, slice: &[M]) {
self.0.insert_slice(index, slice);
}
pub fn insert_slice_split(&mut self, split_idx: usize, slice: &[M]) -> Self {
let tot_len = self.len() + slice.len();
let mid_idx = tot_len / 2;
self.0.insert_slice(split_idx, slice);
let right = LeafSlice::from_slice(&self[mid_idx..]);
self.truncate(mid_idx);
self.0.inline_if_possible();
right
}
pub fn push_slice(&mut self, slice: &[M]) {
let len = self.len();
self.0.insert_slice(len, slice);
}
pub fn push_slice_split(&mut self, slice: &[M]) -> Self {
let len = self.len();
self.insert_slice_split(len, slice)
}
pub fn truncate(&mut self, byte_idx: usize) {
self.0.truncate(byte_idx);
self.0.inline_if_possible();
}
pub fn truncate_front(&mut self, byte_idx: usize) {
self.0.remove_range(0, byte_idx);
self.0.inline_if_possible();
}
pub fn remove_range(&mut self, byte_start: usize, byte_end: usize) {
self.0.remove_range(byte_start, byte_end);
self.0.inline_if_possible();
}
pub fn split_off(&mut self, byte_idx: usize) -> Self {
let other = LeafSlice(self.0.split_off(byte_idx));
self.0.inline_if_possible();
other
}
pub fn zero_width_end(&self) -> bool {
self.0
.as_slice()
.last()
.map(|measurable| measurable.width() == 0)
.unwrap_or(false)
}
}
impl<M> std::cmp::PartialEq for LeafSlice<M>
where
M: Measurable + PartialEq,
{
fn eq(&self, other: &Self) -> bool {
let (s1, s2): (&[M], &[M]) = (self, other);
s1 == s2
}
}
impl<'a, M> PartialEq<LeafSlice<M>> for &'a [M]
where
M: Measurable + PartialEq,
{
fn eq(&self, other: &LeafSlice<M>) -> bool {
*self == (other as &[M])
}
}
impl<'a, M> PartialEq<&'a [M]> for LeafSlice<M>
where
M: Measurable + PartialEq,
{
fn eq(&self, other: &&'a [M]) -> bool {
(self as &[M]) == *other
}
}
impl<M> std::fmt::Display for LeafSlice<M>
where
M: Measurable + Display + Debug,
{
fn fmt(&self, fm: &mut std::fmt::Formatter) -> Result<(), std::fmt::Error> {
LeafSlice::deref(self).fmt(fm)
}
}
impl<M> std::fmt::Debug for LeafSlice<M>
where
M: Measurable + Debug,
{
fn fmt(&self, fm: &mut std::fmt::Formatter) -> std::fmt::Result {
LeafSlice::deref(self).fmt(fm)
}
}
impl<M> Deref for LeafSlice<M>
where
M: Measurable,
{
type Target = [M];
fn deref(&self) -> &[M] {
self.0.as_slice()
}
}
impl<M> AsRef<[M]> for LeafSlice<M>
where
M: Measurable,
{
fn as_ref(&self) -> &[M] {
self.0.as_slice()
}
}
impl<M> Borrow<[M]> for LeafSlice<M>
where
M: Measurable,
{
fn borrow(&self) -> &[M] {
self.0.as_slice()
}
}
mod inner {
use crate::tree::MAX_LEN;
use smallvec::{Array, SmallVec};
use super::Measurable;
#[derive(Copy, Clone)]
struct BackingArray<M>([M; MAX_LEN])
where
M: Measurable;
unsafe impl<M> Array for BackingArray<M>
where
M: Measurable,
{
type Item = M;
fn size() -> usize {
MAX_LEN
}
}
#[derive(Clone, Default)]
#[repr(C)]
pub struct LeafSmallVec<M>
where
M: Measurable,
{
buffer: SmallVec<BackingArray<M>>,
}
impl<M> LeafSmallVec<M>
where
M: Measurable,
{
#[inline(always)]
pub fn with_capacity(capacity: usize) -> Self {
LeafSmallVec {
buffer: SmallVec::with_capacity(capacity),
}
}
#[inline(always)]
pub fn from_slice(slice: &[M]) -> Self {
let mut leaf_small_vec = LeafSmallVec::with_capacity(slice.len());
leaf_small_vec.insert_slice(0, slice);
leaf_small_vec
}
#[inline(always)]
pub fn len(&self) -> usize {
self.buffer.len()
}
pub fn as_slice(&self) -> &[M] {
&self.buffer
}
#[inline(always)]
pub fn insert_slice(&mut self, byte_idx: usize, slice: &[M]) {
self.buffer.insert_from_slice(byte_idx, slice);
}
#[inline(always)]
pub fn remove_range(&mut self, start_byte_idx: usize, end_byte_idx: usize) {
assert!(start_byte_idx <= end_byte_idx);
debug_assert!(end_byte_idx <= self.len());
let len = self.len();
let amt = end_byte_idx - start_byte_idx;
self.buffer.copy_within(end_byte_idx..len, start_byte_idx);
self.buffer.truncate(len - amt);
}
#[inline(always)]
pub fn truncate(&mut self, byte_idx: usize) {
debug_assert!(byte_idx <= self.len());
self.buffer.truncate(byte_idx);
}
#[inline(always)]
pub fn split_off(&mut self, byte_idx: usize) -> Self {
debug_assert!(byte_idx <= self.len());
let len = self.len();
let mut other = LeafSmallVec::with_capacity(len - byte_idx);
other.buffer.extend_from_slice(&self.buffer[byte_idx..]);
self.buffer.truncate(byte_idx);
other
}
#[inline(always)]
pub fn inline_if_possible(&mut self) {
if self.buffer.spilled() && (self.buffer.len() <= self.buffer.inline_size()) {
self.buffer.shrink_to_fit();
}
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Lipsum::*;
#[test]
fn vec_basics() {
let vec = LeafSmallVec::from_slice(&[Lorem, Ipsum, Dolor(3), Sit, Amet]);
assert_eq!(vec.as_slice(), &[Lorem, Ipsum, Dolor(3), Sit, Amet]);
assert_eq!(5, vec.len());
}
#[test]
fn insert_slice_01() {
let mut vec = LeafSmallVec::from_slice(&[Lorem, Ipsum]);
vec.insert_slice(2, &[Dolor(5), Sit, Amet]);
assert_eq!(vec.as_slice(), &[Lorem, Ipsum, Dolor(5), Sit, Amet]);
}
#[test]
#[should_panic]
fn insert_slice_02() {
let mut vec = LeafSmallVec::from_slice(&[Consectur("hi"), Adipiscing(false)]);
vec.insert_slice(3, &[Lorem]);
}
#[test]
fn remove_range_01() {
let mut vec = LeafSmallVec::from_slice(&[Lorem, Ipsum, Dolor(1), Sit, Amet]);
vec.remove_range(2, 3);
assert_eq!(vec.as_slice(), &[Lorem, Ipsum, Sit, Amet]);
}
#[test]
#[should_panic]
fn remove_range_02() {
let mut vec = LeafSmallVec::from_slice(&[Dolor(5), Sit, Amet, Consectur("!!")]);
vec.remove_range(4, 2);
}
#[test]
#[should_panic]
fn remove_range_03() {
let mut vec = LeafSmallVec::from_slice(&[Dolor(5), Sit, Amet, Consectur("!!")]);
vec.remove_range(2, 7);
}
#[test]
fn truncate_01() {
let mut vec = LeafSmallVec::from_slice(&[Dolor(3), Sit, Amet, Consectur("long")]);
vec.truncate(3);
assert_eq!(vec.as_slice(), &[Dolor(3), Sit, Amet]);
}
#[test]
#[should_panic]
fn truncate_02() {
let mut vec = LeafSmallVec::from_slice(&[Dolor(6)]);
vec.truncate(7);
}
#[test]
fn split_off_01() {
let mut vec_1 = LeafSmallVec::from_slice(&[Lorem, Dolor(3), Sit, Amet]);
let vec_2 = vec_1.split_off(2);
assert_eq!(vec_1.as_slice(), &[Lorem, Dolor(3)]);
assert_eq!(vec_2.as_slice(), &[Sit, Amet]);
}
#[test]
#[should_panic]
fn split_off_02() {
let mut s1 = LeafSmallVec::from_slice(&[Lorem, Ipsum, Dolor(3), Sit, Amet]);
s1.split_off(7);
}
}
}