use std::fmt::Debug;
use std::iter::FromIterator;
use std::ops::RangeBounds;
use std::sync::Arc;
use crate::iter::{Chunks, Iter};
use crate::rope_builder::RopeBuilder;
use crate::slice::RopeSlice;
use crate::slice_utils::{start_width_to_index, index_to_width, end_width_to_index};
use crate::tree::{BranchChildren, Node, SliceInfo, MAX_LEN, MIN_LEN};
use crate::{end_bound_to_num, start_bound_to_num, Error, Result};
pub trait Measurable: Clone + Copy {
fn width(&self) -> usize;
}
#[derive(Clone)]
pub struct Rope<M>
where
M: Measurable,
{
pub(crate) root: Arc<Node<M>>,
}
impl<M> Rope<M>
where
M: Measurable,
{
#[inline]
pub fn new() -> Self {
Rope {
root: Arc::new(Node::new()),
}
}
#[inline]
#[allow(clippy::should_implement_trait)]
pub fn from_slice(slice: &[M]) -> Self {
RopeBuilder::new().build_at_once(slice)
}
#[inline]
pub fn len(&self) -> usize {
self.root.len()
}
#[inline]
pub fn width(&self) -> usize {
self.root.width()
}
pub fn capacity(&self) -> usize {
let mut count = 0;
for chunk in self.chunks() {
count += chunk.len().max(MAX_LEN);
}
count
}
pub fn shrink_to_fit(&mut self) {
let mut node_stack = Vec::new();
let mut builder = RopeBuilder::new();
node_stack.push(self.root.clone());
*self = Rope::new();
loop {
if node_stack.is_empty() {
break;
}
if node_stack.last().unwrap().is_leaf() {
builder.append_slice(node_stack.pop().unwrap().leaf_slice());
} else if node_stack.last().unwrap().child_count() == 0 {
node_stack.pop();
} else {
let (_, next_node) = Arc::make_mut(node_stack.last_mut().unwrap())
.children_mut()
.remove(0);
node_stack.push(next_node);
}
}
*self = builder.finish();
}
#[inline]
pub fn insert_slice(&mut self, width: usize, slice: &[M]) {
self.try_insert_slice(width, slice).unwrap()
}
#[inline]
pub fn insert(&mut self, width: usize, measurable: M) {
self.try_insert(width, measurable).unwrap()
}
fn insert_internal(&mut self, width: usize, ins_slice: &[M]) {
let root_info = self.root.slice_info();
let (l_info, residual) = Arc::make_mut(&mut self.root).edit_chunk_at_width(
width,
root_info,
|index, cur_info, leaf_slice| {
let index = end_width_to_index(leaf_slice, index);
if (leaf_slice.len() + ins_slice.len()) <= MAX_LEN {
let new_info = cur_info + SliceInfo::from_slice(ins_slice);
leaf_slice.insert_slice(index, ins_slice);
(new_info, None)
}
else {
let r_slice = leaf_slice.insert_slice_split(index, ins_slice);
let l_slice_info = SliceInfo::from_slice(leaf_slice);
if r_slice.len() > 0 {
let r_slice_info = SliceInfo::from_slice(&r_slice);
(
l_slice_info,
Some((r_slice_info, Arc::new(Node::Leaf(r_slice)))),
)
} else {
(l_slice_info, None)
}
}
},
);
if let Some((r_info, r_node)) = residual {
let mut l_node = Arc::new(Node::new());
std::mem::swap(&mut l_node, &mut self.root);
let mut children = BranchChildren::new();
children.push((l_info, l_node));
children.push((r_info, r_node));
*Arc::make_mut(&mut self.root) = Node::Branch(children);
}
}
pub fn remove<R>(&mut self, width_range: R)
where
R: RangeBounds<usize>,
{
self.try_remove(width_range).unwrap()
}
pub fn split_off(&mut self, width: usize) -> Self {
self.try_split_off(width).unwrap()
}
pub fn append(&mut self, mut other: Self) {
if self.width() == 0 {
std::mem::swap(self, &mut other);
} else if other.width() > 0 {
let left_info = self.root.slice_info();
let right_info = other.root.slice_info();
let l_depth = self.root.depth();
let r_depth = other.root.depth();
if l_depth > r_depth {
let extra =
Arc::make_mut(&mut self.root).append_at_depth(other.root, l_depth - r_depth);
if let Some(node) = extra {
let mut children = BranchChildren::new();
children.push((self.root.slice_info(), Arc::clone(&self.root)));
children.push((node.slice_info(), node));
self.root = Arc::new(Node::Branch(children));
}
} else {
let mut other = other;
let extra = Arc::make_mut(&mut other.root)
.prepend_at_depth(Arc::clone(&self.root), r_depth - l_depth);
if let Some(node) = extra {
let mut children = BranchChildren::new();
children.push((node.slice_info(), node));
children.push((other.root.slice_info(), Arc::clone(&other.root)));
other.root = Arc::new(Node::Branch(children));
}
*self = other;
};
let root = Arc::make_mut(&mut self.root);
if (left_info.len as usize) < MIN_LEN || (right_info.len as usize) < MIN_LEN {
root.fix_tree_seam(left_info.width as usize);
}
self.pull_up_singular_nodes();
}
}
#[inline]
pub fn index_to_width(&self, index: usize) -> usize {
self.try_index_to_width(index).unwrap()
}
#[inline]
pub fn start_width_to_index(&self, width: usize) -> usize {
self.try_start_width_to_index(width).unwrap()
}
#[inline]
pub fn end_width_to_index(&self, width: usize) -> usize {
self.try_end_width_to_index(width).unwrap()
}
#[inline]
pub fn from_index(&self, index: usize) -> (usize, M) {
if let Some(out) = self.get_from_index(index) {
out
} else {
panic!(
"Attempt to index past end of Rope: index {}, Rope length {}",
index,
self.len()
);
}
}
#[inline]
pub fn from_width(&self, width: usize) -> (usize, M) {
if let Some(out) = self.get_from_width(width) {
out
} else {
panic!(
"Attempt to index past end of Rope: char index {}, Rope char length {}",
width,
self.width()
);
}
}
#[inline]
pub fn chunk_at_index(&self, index: usize) -> (&[M], usize, usize) {
if let Some(out) = self.get_chunk_at_index(index) {
out
} else {
panic!(
"Attempt to index past end of Rope: index {}, Rope length {}",
index,
self.len()
);
}
}
#[inline]
pub fn chunk_at_width(&self, width: usize) -> (&[M], usize, usize) {
if let Some(out) = self.get_chunk_at_width(width) {
out
} else {
panic!(
"Attempt to index past end of Rope: char index {}, Rope char length {}",
width,
self.width()
);
}
}
#[inline]
pub fn width_slice<R>(&self, width_range: R) -> RopeSlice<M>
where
R: RangeBounds<usize>,
{
self.get_width_slice(width_range).unwrap()
}
pub fn index_slice<R>(&self, index_range: R) -> RopeSlice<M>
where
R: RangeBounds<usize>,
{
match self.get_index_slice_impl(index_range) {
Ok(s) => return s,
Err(e) => panic!("index_slice(): {}", e),
}
}
#[inline]
pub fn iter(&self) -> Iter<M> {
Iter::new(&self.root)
}
#[inline]
pub fn iter_at_width(&self, width: usize) -> Iter<M> {
if let Some(out) = self.get_iter_at_width(width) {
out
} else {
panic!(
"Attempt to index past end of Rope: index {}, Rope length {}",
width,
self.len()
);
}
}
#[inline]
pub fn chunks(&self) -> Chunks<M> {
Chunks::new(&self.root)
}
#[inline]
pub fn chunks_at_index(&self, index: usize) -> (Chunks<M>, usize, usize) {
if let Some(out) = self.get_chunks_at_index(index) {
out
} else {
panic!(
"Attempt to index past end of Rope: index {}, Rope length {}",
index,
self.len()
);
}
}
#[inline]
pub fn chunks_at_width(&self, width: usize) -> (Chunks<M>, usize, usize) {
if let Some(out) = self.get_chunks_at_width(width) {
out
} else {
panic!(
"Attempt to index past end of Rope: char index {}, Rope char length {}",
width,
self.width()
);
}
}
#[inline]
pub fn is_instance(&self, other: &Self) -> bool {
Arc::ptr_eq(&self.root, &other.root)
}
#[doc(hidden)]
pub fn assert_integrity(&self) {
self.root.assert_integrity();
}
#[doc(hidden)]
pub fn assert_invariants(&self) {
self.root.assert_balance();
self.root.assert_node_size(true);
}
pub(crate) fn pull_up_singular_nodes(&mut self) {
while (!self.root.is_leaf()) && self.root.child_count() == 1 {
let child = if let Node::Branch(ref children) = *self.root {
Arc::clone(&children.nodes()[0])
} else {
unreachable!()
};
self.root = child;
}
}
}
impl<M> Rope<M>
where
M: Measurable,
{
#[inline]
pub fn try_insert_slice(&mut self, width: usize, mut slice: &[M]) -> Result<()> {
if width <= self.width() {
if slice.len() > MAX_LEN * 6 {
let rope = Rope::from_slice(slice);
let right = self.split_off(width);
self.append(rope);
self.append(right);
} else {
while !slice.is_empty() {
let split_index = slice.len() - (MAX_LEN - 4).min(slice.len());
let ins_slice = &slice[split_index..];
slice = &slice[..split_index];
self.insert_internal(width, ins_slice);
}
}
Ok(())
} else {
Err(Error::WidthOutOfBounds(width, self.width()))
}
}
#[inline]
pub fn try_insert(&mut self, width: usize, measurable: M) -> Result<()> {
if width <= self.width() {
self.insert_internal(width, &[measurable]);
Ok(())
} else {
Err(Error::WidthOutOfBounds(width, self.width()))
}
}
pub fn try_remove<R>(&mut self, width_range: R) -> Result<()>
where
R: RangeBounds<usize>,
{
let start_opt = start_bound_to_num(width_range.start_bound());
let end_opt = end_bound_to_num(width_range.end_bound());
let start = start_opt.unwrap_or(0);
let end = end_opt.unwrap_or_else(|| self.width());
if end.max(start) > self.width() {
Err(Error::WidthRangeOutOfBounds(
start_opt,
end_opt,
self.width(),
))
} else if start > end {
Err(Error::WidthRangeInvalid(start, end))
} else {
if start == 0 && end == self.width() {
self.root = Arc::new(Node::new());
return Ok(());
}
let root = Arc::make_mut(&mut self.root);
let root_info = root.slice_info();
let (_, needs_fix) = root.remove_range(start, end, root_info);
if needs_fix {
root.fix_tree_seam(start);
}
self.pull_up_singular_nodes();
Ok(())
}
}
pub fn try_split_off(&mut self, width: usize) -> Result<Self> {
if width <= self.width() {
if width == 0 {
let mut new_rope = Rope::new();
std::mem::swap(self, &mut new_rope);
Ok(new_rope)
} else if width == self.width() {
Ok(Rope::new())
} else {
let mut new_rope = Rope {
root: Arc::new(Arc::make_mut(&mut self.root).end_split(width)),
};
Arc::make_mut(&mut self.root).zip_fix_right();
Arc::make_mut(&mut new_rope.root).zip_fix_left();
self.pull_up_singular_nodes();
new_rope.pull_up_singular_nodes();
Ok(new_rope)
}
} else {
Err(Error::WidthOutOfBounds(width, self.width()))
}
}
#[inline]
pub fn try_index_to_width(&self, index: usize) -> Result<usize> {
if index <= self.len() {
let (chunk, b, c) = self.chunk_at_index(index);
Ok(c + index_to_width(chunk, index - b))
} else {
Err(Error::IndexOutOfBounds(index, self.len()))
}
}
#[inline]
pub fn try_start_width_to_index(&self, width: usize) -> Result<usize> {
if width <= self.width() {
let (chunk, b, c) = self.chunk_at_width(width);
Ok(b + start_width_to_index(chunk, width - c))
} else {
Err(Error::WidthOutOfBounds(width, self.width()))
}
}
#[inline]
pub fn try_end_width_to_index(&self, width: usize) -> Result<usize> {
if width <= self.width() {
let (chunk, b, c) = self.chunk_at_width(width);
Ok(b + end_width_to_index(chunk, width - c))
} else {
Err(Error::WidthOutOfBounds(width, self.width()))
}
}
#[inline]
pub fn get_from_index(&self, index: usize) -> Option<(usize, M)> {
if index < self.len() {
let (chunk, chunk_index, chunk_width) = self.chunk_at_index(index);
let chunk_rel_index = index - chunk_index;
let width = index_to_width(chunk, chunk_rel_index);
Some((width + chunk_width, chunk[chunk_rel_index]))
} else {
None
}
}
#[inline]
pub fn get_from_width(&self, width: usize) -> Option<(usize, M)> {
if width < self.width() {
let (chunk, _, chunk_width) = self.chunk_at_width(width);
let index = start_width_to_index(chunk, width - chunk_width);
let width = index_to_width(chunk, index);
Some((width + chunk_width, chunk[index]))
} else {
None
}
}
#[inline]
pub fn get_chunk_at_index(&self, index: usize) -> Option<(&[M], usize, usize)> {
if index <= self.len() {
let (chunk, info) = self.root.get_chunk_at_index(index);
Some((chunk, info.len as usize, info.width as usize))
} else {
None
}
}
#[inline]
pub fn get_chunk_at_width(&self, width: usize) -> Option<(&[M], usize, usize)> {
if width <= self.width() {
let (chunk, info) = self.root.get_first_chunk_at_width(width);
Some((chunk, info.len as usize, info.width as usize))
} else {
None
}
}
#[inline]
pub fn get_width_slice<R>(&self, width_range: R) -> Option<RopeSlice<M>>
where
R: RangeBounds<usize>,
{
let start = start_bound_to_num(width_range.start_bound()).unwrap_or(0);
let end = end_bound_to_num(width_range.end_bound()).unwrap_or_else(|| self.width());
if start <= end && end <= self.width() {
Some(RopeSlice::new_with_range(&self.root, start, end))
} else {
None
}
}
#[inline]
pub fn get_index_slice<R>(&self, index_range: R) -> Option<RopeSlice<M>>
where
R: RangeBounds<usize>,
{
self.get_index_slice_impl(index_range).ok()
}
pub(crate) fn get_index_slice_impl<R>(&self, index_range: R) -> Result<RopeSlice<M>>
where
R: RangeBounds<usize>,
{
let start_range = start_bound_to_num(index_range.start_bound());
let end_range = end_bound_to_num(index_range.end_bound());
match (start_range, end_range) {
(Some(s), Some(e)) => {
if s > e {
return Err(Error::IndexRangeInvalid(s, e));
} else if e > self.len() {
return Err(Error::IndexRangeOutOfBounds(
start_range,
end_range,
self.len(),
));
}
}
(Some(s), None) => {
if s > self.len() {
return Err(Error::IndexRangeOutOfBounds(
start_range,
end_range,
self.len(),
));
}
}
(None, Some(e)) => {
if e > self.len() {
return Err(Error::IndexRangeOutOfBounds(None, end_range, self.len()));
}
}
_ => {}
}
let (start, end) = (
start_range.unwrap_or(0),
end_range.unwrap_or_else(|| self.len()),
);
RopeSlice::new_with_index_range(&self.root, start, end)
}
#[inline]
pub fn get_iter_at_width(&self, width: usize) -> Option<Iter<M>> {
if width <= self.width() {
Some(Iter::new_with_range_at_width(
&self.root,
width,
(0, self.len()),
(0, self.width()),
))
} else {
None
}
}
#[inline]
pub fn get_chunks_at_index(&self, index: usize) -> Option<(Chunks<M>, usize, usize)> {
if index <= self.len() {
Some(Chunks::new_with_range_at_index(
&self.root,
index,
(0, self.len()),
(0, self.width()),
))
} else {
None
}
}
#[inline]
pub fn get_chunks_at_width(&self, width: usize) -> Option<(Chunks<M>, usize, usize)> {
if width <= self.width() {
Some(Chunks::new_with_range_at_width(
&self.root,
width,
(0, self.len()),
(0, self.width()),
))
} else {
None
}
}
}
impl<'a, M> From<&'a [M]> for Rope<M>
where
M: Measurable,
{
#[inline]
fn from(slice: &'a [M]) -> Self {
Rope::from_slice(slice)
}
}
impl<'a, M> From<std::borrow::Cow<'a, [M]>> for Rope<M>
where
M: Measurable,
{
#[inline]
fn from(slice: std::borrow::Cow<'a, [M]>) -> Self {
Rope::from_slice(&slice)
}
}
impl<M> From<Vec<M>> for Rope<M>
where
M: Measurable,
{
#[inline]
fn from(slice: Vec<M>) -> Self {
Rope::from_slice(&slice)
}
}
impl<'a, M> From<RopeSlice<'a, M>> for Rope<M>
where
M: Measurable,
{
fn from(s: RopeSlice<'a, M>) -> Self {
use crate::slice::RSEnum;
match s {
RopeSlice(RSEnum::Full {
node,
start_info,
end_info,
}) => {
let mut rope = Rope {
root: Arc::clone(node),
};
if end_info.width < node.slice_info().width {
{
let root = Arc::make_mut(&mut rope.root);
root.end_split(end_info.width as usize);
root.zip_fix_right();
}
rope.pull_up_singular_nodes();
}
if start_info.width > 0 {
{
let root = Arc::make_mut(&mut rope.root);
*root = root.start_split(start_info.width as usize);
root.zip_fix_left();
}
rope.pull_up_singular_nodes();
}
rope
}
RopeSlice(RSEnum::Light { slice, .. }) => Rope::from_slice(slice),
}
}
}
impl<M> From<Rope<M>> for Vec<M>
where
M: Measurable,
{
#[inline]
fn from(r: Rope<M>) -> Self {
Vec::from(&r)
}
}
impl<'a, M> From<&'a Rope<M>> for Vec<M>
where
M: Measurable,
{
#[inline]
fn from(r: &'a Rope<M>) -> Self {
let mut vec = Vec::with_capacity(r.len());
vec.extend(
r.chunks()
.map(|chunk| chunk.iter())
.flatten()
.map(|measurable| *measurable),
);
vec
}
}
impl<'a, M> From<Rope<M>> for std::borrow::Cow<'a, [M]>
where
M: Measurable,
{
#[inline]
fn from(r: Rope<M>) -> Self {
std::borrow::Cow::Owned(Vec::from(r))
}
}
impl<'a, M> From<&'a Rope<M>> for std::borrow::Cow<'a, [M]>
where
M: Measurable,
{
#[inline]
fn from(r: &'a Rope<M>) -> Self {
if let Node::Leaf(ref slice) = *r.root {
std::borrow::Cow::Borrowed(slice)
} else {
std::borrow::Cow::Owned(Vec::from(r))
}
}
}
impl<'a, M> FromIterator<&'a [M]> for Rope<M>
where
M: Measurable,
{
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = &'a [M]>,
{
let mut builder = RopeBuilder::new();
for chunk in iter {
builder.append_slice(chunk);
}
builder.finish()
}
}
impl<'a, M> FromIterator<std::borrow::Cow<'a, [M]>> for Rope<M>
where
M: Measurable,
{
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = std::borrow::Cow<'a, [M]>>,
{
let mut builder = RopeBuilder::new();
for chunk in iter {
builder.append_slice(&chunk);
}
builder.finish()
}
}
impl<'a, M> FromIterator<Vec<M>> for Rope<M>
where
M: Measurable,
{
fn from_iter<T>(iter: T) -> Self
where
T: IntoIterator<Item = Vec<M>>,
{
let mut builder = RopeBuilder::new();
for chunk in iter {
builder.append_slice(&chunk);
}
builder.finish()
}
}
impl<M> std::fmt::Debug for Rope<M>
where
M: Measurable + Debug,
{
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_list().entries(self.chunks()).finish()
}
}
impl<M> std::fmt::Display for Rope<M>
where
M: Measurable + Debug,
{
#[inline]
fn fmt(&self, f: &mut std::fmt::Formatter) -> std::fmt::Result {
f.debug_list().entries(self.chunks()).finish()
}
}
impl<M> std::default::Default for Rope<M>
where
M: Measurable,
{
#[inline]
fn default() -> Self {
Self::new()
}
}
impl<M> std::cmp::Eq for Rope<M> where M: Measurable + Eq {}
impl<M> std::cmp::PartialEq<Rope<M>> for Rope<M>
where
M: Measurable + PartialEq,
{
#[inline]
fn eq(&self, other: &Rope<M>) -> bool {
self.width_slice(..) == other.width_slice(..)
}
}
impl<'a, M> std::cmp::PartialEq<&'a [M]> for Rope<M>
where
M: Measurable + PartialEq,
{
#[inline]
fn eq(&self, other: &&'a [M]) -> bool {
self.width_slice(..) == *other
}
}
impl<'a, M> std::cmp::PartialEq<Rope<M>> for &'a [M]
where
M: Measurable + PartialEq,
{
#[inline]
fn eq(&self, other: &Rope<M>) -> bool {
*self == other.width_slice(..)
}
}
impl<M> std::cmp::PartialEq<[M]> for Rope<M>
where
M: Measurable + PartialEq,
{
#[inline]
fn eq(&self, other: &[M]) -> bool {
self.width_slice(..) == other
}
}
impl<M> std::cmp::PartialEq<Rope<M>> for [M]
where
M: Measurable + PartialEq,
{
#[inline]
fn eq(&self, other: &Rope<M>) -> bool {
self == other.width_slice(..)
}
}
impl<'a, M> std::cmp::PartialEq<Vec<M>> for Rope<M>
where
M: Measurable + PartialEq,
{
#[inline]
fn eq(&self, other: &Vec<M>) -> bool {
self.width_slice(..) == other.as_slice()
}
}
impl<'a, M> std::cmp::PartialEq<Rope<M>> for Vec<M>
where
M: Measurable + PartialEq,
{
#[inline]
fn eq(&self, other: &Rope<M>) -> bool {
self.as_slice() == other.width_slice(..)
}
}
impl<'a, M> std::cmp::PartialEq<std::borrow::Cow<'a, [M]>> for Rope<M>
where
M: Measurable + PartialEq,
{
#[inline]
fn eq(&self, other: &std::borrow::Cow<'a, [M]>) -> bool {
self.width_slice(..) == **other
}
}
impl<'a, M> std::cmp::PartialEq<Rope<M>> for std::borrow::Cow<'a, [M]>
where
M: Measurable + PartialEq,
{
#[inline]
fn eq(&self, other: &Rope<M>) -> bool {
**self == other.width_slice(..)
}
}
impl<M> std::cmp::Ord for Rope<M>
where
M: Measurable + Ord,
{
#[inline]
fn cmp(&self, other: &Rope<M>) -> std::cmp::Ordering {
self.width_slice(..).cmp(&other.width_slice(..))
}
}
impl<M> std::cmp::PartialOrd<Rope<M>> for Rope<M>
where
M: Measurable + PartialOrd + Ord,
{
#[inline]
fn partial_cmp(&self, other: &Rope<M>) -> Option<std::cmp::Ordering> {
Some(self.cmp(other))
}
}
#[cfg(test)]
mod tests {
use super::*;
use crate::Lipsum::{self, *};
fn lorem_ipsum() -> Vec<Lipsum> {
(0..70)
.into_iter()
.map(|num| match num % 14 {
0 | 7 => Lorem,
1 | 8 => Ipsum,
2 => Dolor(4),
3 | 10 => Sit,
4 | 11 => Amet,
5 => Consectur("hello"),
6 => Adipiscing(true),
9 => Dolor(8),
12 => Consectur("bye"),
13 => Adipiscing(false),
_ => unreachable!(),
})
.collect()
}
const SHORT_LOREM: &[Lipsum] = &[Lorem, Ipsum, Dolor(3), Sit, Amet];
#[test]
fn new_01() {
let rope: Rope<Lipsum> = Rope::new();
assert_eq!(rope, [].as_slice());
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn from_slice() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
assert_eq!(rope, lorem_ipsum());
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn len_01() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
assert_eq!(rope.len(), 70);
}
#[test]
fn width_02() {
let rope: Rope<Lipsum> = Rope::from_slice(&[]);
assert_eq!(rope.len(), 0);
}
#[test]
fn len_from_widths_01() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
assert_eq!(rope.width(), 135);
}
#[test]
fn len_from_widths_02() {
let rope: Rope<Lipsum> = Rope::from_slice(&[]);
assert_eq!(rope.width(), 0);
}
#[test]
fn insert_01() {
let mut rope = Rope::from_slice(SHORT_LOREM);
rope.insert_slice(3, &[Lorem, Ipsum, Dolor(3)]);
assert_eq!(
rope,
[Lorem, Ipsum, Lorem, Ipsum, Dolor(3), Dolor(3), Sit, Amet].as_slice()
);
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn insert_02() {
let mut rope = Rope::from_slice(SHORT_LOREM);
rope.insert_slice(0, &[Lorem, Ipsum, Dolor(3)]);
assert_eq!(
rope,
[Lorem, Ipsum, Dolor(3), Lorem, Ipsum, Dolor(3), Sit, Amet].as_slice()
);
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn insert_03() {
let mut rope = Rope::from_slice(SHORT_LOREM);
rope.insert_slice(6, &[Lorem, Ipsum, Dolor(3)]);
assert_eq!(
rope,
[Lorem, Ipsum, Dolor(3), Sit, Amet, Lorem, Ipsum, Dolor(3)].as_slice()
);
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn insert_04() {
let mut rope = Rope::new();
rope.insert_slice(0, &[Lorem, Ipsum]);
rope.insert_slice(2, &[Dolor(5)]);
rope.insert_slice(3, &[Sit]);
rope.insert_slice(4, &[Consectur("test")]);
rope.insert_slice(11, &[Dolor(3)]);
assert_eq!(
rope,
[Lorem, Ipsum, Sit, Dolor(5), Consectur("test"), Dolor(3)].as_slice()
);
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn insert_05() {
let mut rope = Rope::new();
rope.insert_slice(0, &[Dolor(15), Dolor(20)]);
rope.insert_slice(7, &[Sit, Amet]);
assert_eq!(rope, [Dolor(15), Sit, Amet, Dolor(20)].as_slice());
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn insert_06() {
let mut rope = Rope::new();
rope.insert(0, Dolor(15));
rope.insert(1, Dolor(20));
rope.insert(2, Dolor(10));
rope.insert(3, Dolor(4));
rope.insert_slice(20, &[Sit, Amet]);
assert_eq!(
rope,
[Dolor(15), Dolor(4), Dolor(10), Sit, Amet, Dolor(20)].as_slice()
);
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn remove_01() {
let slice = &[Dolor(15), Sit, Amet, Dolor(24), Lorem, Ipsum, Dolor(7)];
let mut rope = Rope::from_slice(slice);
rope.remove(0..11); rope.remove(24..31); rope.remove(0..0); assert_eq!(rope, [Dolor(24)].as_slice());
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn remove_02() {
let slice = &[Lorem; 15];
let mut rope = Rope::from_slice(slice);
rope.remove(3..6);
assert_eq!(rope, [Lorem; 12].as_slice());
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn remove_03() {
let mut rope = Rope::from_slice(lorem_ipsum().as_slice());
rope.remove(45..45);
assert_eq!(rope, lorem_ipsum());
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn remove_04() {
let mut rope = Rope::from_slice(lorem_ipsum().as_slice());
rope.remove(0..135);
assert_eq!(rope, [].as_slice());
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn remove_05() {
let mut rope = Rope::from_slice(lorem_ipsum().as_slice());
rope.remove(3..135);
assert_eq!(rope, &lorem_ipsum()[..2]);
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
#[should_panic]
fn remove_06() {
let mut rope = Rope::from_slice(lorem_ipsum().as_slice());
#[allow(clippy::reversed_empty_ranges)]
rope.remove(56..55); }
#[test]
#[should_panic]
fn remove_07() {
let mut rope = Rope::from_slice(lorem_ipsum().as_slice());
rope.remove(134..136); }
#[test]
fn split_off_01() {
let mut rope = Rope::from_slice(lorem_ipsum().as_slice());
let split = rope.split_off(50);
assert_eq!(rope, &lorem_ipsum()[..24]);
assert_eq!(split, &lorem_ipsum()[24..]);
rope.assert_integrity();
split.assert_integrity();
rope.assert_invariants();
split.assert_invariants();
}
#[test]
fn split_off_02() {
let mut rope = Rope::from_slice(lorem_ipsum().as_slice());
let split = rope.split_off(1);
assert_eq!(rope, [Lorem].as_slice());
assert_eq!(split, &lorem_ipsum()[1..]);
rope.assert_integrity();
split.assert_integrity();
rope.assert_invariants();
split.assert_invariants();
}
#[test]
fn split_off_03() {
let mut rope = Rope::from_slice(lorem_ipsum().as_slice());
let split = rope.split_off(134);
assert_eq!(rope, &lorem_ipsum()[..69]);
assert_eq!(split, [Adipiscing(false)].as_slice());
rope.assert_integrity();
split.assert_integrity();
rope.assert_invariants();
split.assert_invariants();
}
#[test]
fn split_off_04() {
let mut rope = Rope::from_slice(lorem_ipsum().as_slice());
let split = rope.split_off(0);
assert_eq!(rope, [].as_slice());
assert_eq!(split, lorem_ipsum().as_slice());
rope.assert_integrity();
split.assert_integrity();
rope.assert_invariants();
split.assert_invariants();
}
#[test]
fn split_off_05() {
let mut rope = Rope::from_slice(lorem_ipsum().as_slice());
let split = rope.split_off(135);
assert_eq!(rope, lorem_ipsum().as_slice());
assert_eq!(split, [].as_slice());
rope.assert_integrity();
split.assert_integrity();
rope.assert_invariants();
split.assert_invariants();
}
#[test]
#[should_panic]
fn split_off_06() {
let mut rope = Rope::from_slice(lorem_ipsum().as_slice());
rope.split_off(136); }
#[test]
fn append_01() {
let mut rope = Rope::from_slice(&lorem_ipsum()[..35]);
let append = Rope::from_slice(&lorem_ipsum()[35..]);
rope.append(append);
assert_eq!(rope, lorem_ipsum().as_slice());
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn append_02() {
let mut rope = Rope::from_slice(&lorem_ipsum()[..68]);
let append = Rope::from_slice(&[Consectur("bye"), Adipiscing(false)]);
rope.append(append);
assert_eq!(rope, lorem_ipsum());
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn append_03() {
let mut rope = Rope::from_slice(&[Lorem, Ipsum]);
let append = Rope::from_slice(&lorem_ipsum()[2..]);
rope.append(append);
assert_eq!(rope, lorem_ipsum());
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn append_04() {
let mut rope = Rope::from_slice(lorem_ipsum().as_slice());
let append = Rope::from_slice([].as_slice());
rope.append(append);
assert_eq!(rope, lorem_ipsum());
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn append_05() {
let mut rope = Rope::from_slice([].as_slice());
let append = Rope::from_slice(lorem_ipsum().as_slice());
rope.append(append);
assert_eq!(rope, lorem_ipsum());
rope.assert_integrity();
rope.assert_invariants();
}
#[test]
fn width_to_index_01() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
assert_eq!(rope.start_width_to_index(0), 0);
assert_eq!(rope.start_width_to_index(1), 1);
assert_eq!(rope.start_width_to_index(2), 1);
assert_eq!(rope.start_width_to_index(91), 47);
assert_eq!(rope.start_width_to_index(92), 47);
assert_eq!(rope.start_width_to_index(93), 48);
assert_eq!(rope.start_width_to_index(94), 49);
assert_eq!(rope.start_width_to_index(102), 51);
assert_eq!(rope.start_width_to_index(103), 51);
}
#[test]
fn from_index_01() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
assert_eq!(rope.from_index(0), (0, Lorem));
assert_eq!(rope.from_index(67), (132, Amet));
assert_eq!(rope.from_index(68), (132, Consectur("bye")));
assert_eq!(rope.from_index(69), (135, Adipiscing(false)));
}
#[test]
#[should_panic]
fn from_index_02() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
rope.from_index(70);
}
#[test]
#[should_panic]
fn from_index_03() {
let rope: Rope<Lipsum> = Rope::from_slice(&[]);
rope.from_index(0);
}
#[test]
fn from_width_01() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
assert_eq!(rope.from_width(0), (0, Lorem));
assert_eq!(rope.from_width(10), (7, Consectur("hello")));
assert_eq!(rope.from_width(18), (16, Dolor(8)));
assert_eq!(rope.from_width(108), (108, Adipiscing(false)));
}
#[test]
#[should_panic]
fn from_width_02() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
rope.from_width(136);
}
#[test]
#[should_panic]
fn from_width_03() {
let rope: Rope<Lipsum> = Rope::from_slice(&[]);
rope.from_width(0);
}
#[test]
fn chunk_at_index() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let lorem_ipsum = lorem_ipsum();
let mut total = lorem_ipsum.as_slice();
let mut last_chunk = [].as_slice();
for i in 0..rope.len() {
let (chunk, index, width) = rope.chunk_at_index(i);
assert_eq!(width, index_to_width(&lorem_ipsum, index));
if chunk != last_chunk {
assert_eq!(chunk, &total[..chunk.len()]);
total = &total[chunk.len()..];
last_chunk = chunk;
}
let lipsum_1 = lorem_ipsum.iter().nth(i).unwrap();
let lipsum_2 = {
let i2 = i - index;
chunk.iter().nth(i2).unwrap()
};
assert_eq!(lipsum_1, lipsum_2);
}
assert_eq!(total.len(), 0);
}
#[test]
fn chunk_at_width() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let lorem_ipsum = lorem_ipsum();
let mut total = lorem_ipsum.as_slice();
let mut last_chunk = [].as_slice();
for i in 0..rope.width() {
let (chunk, _, width) = rope.chunk_at_width(i);
if chunk != last_chunk {
assert_eq!(chunk, &total[..chunk.len()]);
total = &total[chunk.len()..];
last_chunk = chunk;
}
let lipsum_1 = {
let index_1 = start_width_to_index(&lorem_ipsum, i);
lorem_ipsum.iter().nth(index_1).unwrap()
};
let lipsum_2 = {
let index_2 = start_width_to_index(&chunk, i - width);
chunk.iter().nth(index_2).unwrap()
};
assert_eq!(lipsum_1, lipsum_2);
}
assert_eq!(total.len(), 0);
}
#[test]
fn width_slice_01() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let slice = rope.width_slice(0..rope.width());
assert_eq!(slice, lorem_ipsum());
}
#[test]
fn width_slice_02() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let slice = rope.width_slice(5..21);
assert_eq!(slice, &lorem_ipsum()[2..10]);
}
#[test]
fn width_slice_03() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let slice = rope.width_slice(31..135);
assert_eq!(slice, &lorem_ipsum()[16..70]);
}
#[test]
fn width_slice_04() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let slice = rope.width_slice(53..53);
assert_eq!([].as_slice(), slice);
}
#[test]
#[should_panic]
fn width_slice_05() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
#[allow(clippy::reversed_empty_ranges)]
rope.width_slice(53..52); }
#[test]
#[should_panic]
fn width_slice_06() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
rope.width_slice(134..136);
}
#[test]
fn index_slice_01() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let slice = rope.index_slice(0..rope.len());
assert_eq!(lorem_ipsum(), slice);
}
#[test]
fn index_slice_02() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let slice = rope.index_slice(5..21);
assert_eq!(&lorem_ipsum()[5..21], slice);
}
#[test]
fn index_slice_03() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let slice = rope.index_slice(31..55);
assert_eq!(&lorem_ipsum()[31..55], slice);
}
#[test]
fn index_slice_04() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let slice = rope.index_slice(53..53);
assert_eq!([].as_slice(), slice);
}
#[test]
#[should_panic]
fn index_slice_05() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
#[allow(clippy::reversed_empty_ranges)]
rope.index_slice(53..52); }
#[test]
#[should_panic]
fn index_slice_06() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
rope.index_slice(20..72);
}
#[test]
fn eq_rope_01() {
let rope: Rope<Lipsum> = Rope::from_slice([].as_slice());
assert_eq!(rope, rope);
}
#[test]
fn eq_rope_02() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
assert_eq!(rope, rope);
}
#[test]
fn eq_rope_03() {
let rope_1 = Rope::from_slice(lorem_ipsum().as_slice());
let mut rope_2 = rope_1.clone();
rope_2.remove(26..27);
rope_2.insert(26, Dolor(1000));
assert_ne!(rope_1, rope_2);
}
#[test]
fn eq_rope_04() {
let rope: Rope<Lipsum> = Rope::from_slice([].as_slice());
assert_eq!(rope, [].as_slice());
assert_eq!([].as_slice(), rope);
}
#[test]
fn eq_rope_05() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
assert_eq!(rope, lorem_ipsum());
assert_eq!(lorem_ipsum(), rope);
}
#[test]
fn eq_rope_06() {
let mut rope = Rope::from_slice(lorem_ipsum().as_slice());
rope.remove(26..27);
rope.insert(26, Dolor(5000));
assert_ne!(rope, lorem_ipsum());
assert_ne!(lorem_ipsum(), rope);
}
#[test]
fn eq_rope_07() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let slice: Vec<Lipsum> = lorem_ipsum().into();
assert_eq!(rope, slice);
assert_eq!(slice, rope);
}
#[test]
fn to_vec_01() {
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let slice: Vec<Lipsum> = (&rope).into();
assert_eq!(rope, slice);
}
#[test]
fn to_cow_01() {
use std::borrow::Cow;
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let cow: Cow<[Lipsum]> = (&rope).into();
assert_eq!(rope, cow);
}
#[test]
fn to_cow_02() {
use std::borrow::Cow;
let rope = Rope::from_slice(lorem_ipsum().as_slice());
let cow: Cow<[Lipsum]> = (rope.clone()).into();
assert_eq!(rope, cow);
}
#[test]
fn to_cow_03() {
use std::borrow::Cow;
let rope = Rope::from_slice(&[Lorem]);
let cow: Cow<[Lipsum]> = (&rope).into();
if let Cow::Owned(_) = cow {
panic!("Small Cow conversions should result in a borrow.");
}
assert_eq!(rope, cow);
}
#[test]
fn from_rope_slice_01() {
let rope_1 = Rope::from_slice(lorem_ipsum().as_slice());
let slice = rope_1.width_slice(..);
let rope_2: Rope<Lipsum> = slice.into();
assert_eq!(rope_1, rope_2);
assert_eq!(slice, rope_2);
}
#[test]
fn from_rope_slice_02() {
let rope_1 = Rope::from_slice(lorem_ipsum().as_slice());
let slice = rope_1.width_slice(0..24);
let rope_2: Rope<Lipsum> = slice.into();
assert_eq!(slice, rope_2);
}
#[test]
fn from_rope_slice_03() {
let rope_1 = Rope::from_slice(lorem_ipsum().as_slice());
let slice = rope_1.width_slice(13..89);
let rope_2: Rope<Lipsum> = slice.into();
assert_eq!(slice, rope_2);
}
#[test]
fn from_rope_slice_04() {
let rope_1 = Rope::from_slice(lorem_ipsum().as_slice());
let slice = rope_1.width_slice(13..41);
let rope_2: Rope<Lipsum> = slice.into();
assert_eq!(slice, rope_2);
}
#[test]
fn from_iter_01() {
let rope_1 = Rope::from_slice(lorem_ipsum().as_slice());
let rope_2 = Rope::from_iter(rope_1.chunks());
assert_eq!(rope_1, rope_2);
}
#[test]
fn is_instance_01() {
let rope = Rope::from_slice(&[Lorem, Ipsum, Dolor(10), Sit, Amet]);
let mut c1 = rope.clone();
let c2 = c1.clone();
assert!(rope.is_instance(&c1));
assert!(rope.is_instance(&c2));
assert!(c1.is_instance(&c2));
c1.insert_slice(0, &[Consectur("oh noes!")]);
assert!(!rope.is_instance(&c1));
assert!(rope.is_instance(&c2));
assert!(!c1.is_instance(&c2));
}
}