led/src/buffer/rope.rs
Nathan Vegdahl 6eed3fcc74 Improved file load times.
There was a regression after switching to ropes.  Now it's pretty much
back to pre-rope load times.
2015-02-15 20:15:19 -08:00

1459 lines
49 KiB
Rust

use std::cmp::{min, max};
use std::mem;
use std::str::Graphemes;
use std::ops::Index;
use string_utils::{grapheme_count, insert_text_at_grapheme_index, remove_text_between_grapheme_indices, split_string_at_grapheme_index, grapheme_pos_to_byte_pos};
const MIN_NODE_SIZE: usize = 64;
const MAX_NODE_SIZE: usize = MIN_NODE_SIZE * 2;
/// A rope data structure for storing text in a format that is efficient
/// for insertion and removal even for extremely large strings.
pub struct Rope {
data: RopeData,
grapheme_count_: usize,
tree_height: u32,
}
enum RopeData {
Leaf(String),
Branch(Box<Rope>, Box<Rope>),
}
impl Rope {
/// Creates a new empty rope
pub fn new() -> Rope {
Rope {
data: RopeData::Leaf(String::new()),
grapheme_count_: 0,
tree_height: 1,
}
}
/// Creates a new rope from a string slice
pub fn new_from_str(s: &str) -> Rope {
let mut rope_stack: Vec<Rope> = Vec::new();
let mut s1 = s;
loop {
// Get the next chunk of the string to add
let mut i = 0;
let mut byte_i = 0;
for (bi, g) in s1.grapheme_indices(true) {
byte_i = bi + g.len();
i += 1;
if i >= MAX_NODE_SIZE {
break;
}
}
if i == 0 {
break;
}
let chunk = &s1[..byte_i];
// Add chunk
rope_stack.push(Rope {
data: RopeData::Leaf(String::from_str(chunk)),
grapheme_count_: i,
tree_height: 1,
});
// Do merges
loop {
let rsl = rope_stack.len();
if rsl > 1 && rope_stack[rsl-2].tree_height <= rope_stack[rsl-1].tree_height {
let right = Box::new(rope_stack.pop().unwrap());
let left = Box::new(rope_stack.pop().unwrap());
let h = max(left.tree_height, right.tree_height) + 1;
let gc = left.grapheme_count_ + right.grapheme_count_;
rope_stack.push(Rope {
data: RopeData::Branch(left, right),
grapheme_count_: gc,
tree_height: h,
});
}
else {
break;
}
}
s1 = &s1[byte_i..];
}
// Handle possible final unmerged case
let rope = if rope_stack.len() == 0 {
Rope::new()
}
else {
while rope_stack.len() > 1 {
let right = Box::new(rope_stack.pop().unwrap());
let left = Box::new(rope_stack.pop().unwrap());
let h = max(left.tree_height, right.tree_height) + 1;
let gc = left.grapheme_count_ + right.grapheme_count_;
rope_stack.push(Rope {
data: RopeData::Branch(left, right),
grapheme_count_: gc,
tree_height: h,
});
}
rope_stack.pop().unwrap()
};
return rope;
}
pub fn new_from_str_with_count(s: &str, count: usize) -> Rope {
if count <= MAX_NODE_SIZE {
Rope {
data: RopeData::Leaf(String::from_str(s)),
grapheme_count_: count,
tree_height: 1,
}
}
else {
Rope::new_from_str(s)
}
}
/// Creates a new rope from a string, consuming the string
pub fn new_from_string(s: String) -> Rope {
// TODO: special case short strings?
Rope::new_from_str(s.as_slice())
}
pub fn grapheme_count(&self) -> usize {
return self.grapheme_count_;
}
pub fn insert_text_at_grapheme_index(&mut self, text: &str, pos: usize) {
match self.data {
// Find node for text to be inserted into
RopeData::Branch(ref mut left, ref mut right) => {
if pos < left.grapheme_count_ {
left.insert_text_at_grapheme_index(text, pos);
}
else {
right.insert_text_at_grapheme_index(text, pos - left.grapheme_count_);
}
},
// Insert the text
RopeData::Leaf(ref mut s_text) => {
insert_text_at_grapheme_index(s_text, text, pos);
},
}
self.update_stats();
self.split_if_too_large();
self.rebalance();
}
pub fn remove_text_between_grapheme_indices(&mut self, pos_a: usize, pos_b: usize) {
// Bounds checks
if pos_a > pos_b {
panic!("Rope::remove_text_between_grapheme_indices(): pos_a must be less than or equal to pos_b.");
}
if pos_b > self.grapheme_count_ {
panic!("Rope::remove_text_between_grapheme_indices(): attempt to remove text after end of node text.");
}
match self.data {
RopeData::Leaf(ref mut text) => {
remove_text_between_grapheme_indices(text, pos_a, pos_b);
},
RopeData::Branch(ref mut left, ref mut right) => {
let lgc = left.grapheme_count_;
if pos_a < lgc {
left.remove_text_between_grapheme_indices(pos_a, min(pos_b, lgc));
}
if pos_b > lgc {
right.remove_text_between_grapheme_indices(pos_a - min(pos_a, lgc), pos_b - lgc);
}
}
}
self.update_stats();
self.merge_if_too_small();
self.rebalance();
}
/// Splits a rope into two pieces from the given grapheme index.
/// The first piece remains in this rope, the second piece is returned
/// as a new rope.
pub fn split(&mut self, pos: usize) -> Rope {
// TODO: make more efficient.
let s = self.to_string();
let gc = self.grapheme_count();
let bp = grapheme_pos_to_byte_pos(s.as_slice(), pos);
self.remove_text_between_grapheme_indices(pos, gc);
Rope::new_from_str(&s.as_slice()[bp..])
}
/// Appends another rope to the end of this one, consuming the other rope.
pub fn append(&mut self, rope: Rope) {
// TODO: make more efficient. Converting to a string and then
// inserting is pretty slow...
let s = rope.to_string();
let gc = self.grapheme_count();
self.insert_text_at_grapheme_index(s.as_slice(), gc);
}
/// Makes a copy of the rope as a string
pub fn to_string(&self) -> String {
let mut s = String::new();
for chunk in self.chunk_iter() {
s.push_str(chunk);
}
return s;
}
/// Creates a chunk iterator for the rope
pub fn chunk_iter<'a>(&'a self) -> RopeChunkIter<'a> {
self.chunk_iter_at_index(0).1
}
/// Creates a chunk iter starting at the chunk containing the given
/// grapheme index. Returns the chunk and its starting grapheme index.
pub fn chunk_iter_at_index<'a>(&'a self, index: usize) -> (usize, RopeChunkIter<'a>) {
let mut node_stack: Vec<&'a Rope> = Vec::new();
let mut cur_node = self;
let mut grapheme_i = index;
// Find the right rope node, and populate the stack at the same time
loop {
match cur_node.data {
RopeData::Leaf(_) => {
node_stack.push(cur_node);
break;
},
RopeData::Branch(ref left, ref right) => {
if grapheme_i < left.grapheme_count_ {
node_stack.push(&(**right));
cur_node = &(**left);
}
else {
cur_node = &(**right);
grapheme_i -= left.grapheme_count_;
}
}
}
}
(index - grapheme_i, RopeChunkIter {node_stack: node_stack})
}
/// Creates an iterator at the first grapheme of the rope
pub fn grapheme_iter<'a>(&'a self) -> RopeGraphemeIter<'a> {
self.grapheme_iter_at_index(0)
}
/// Creates an iterator at the given grapheme index
pub fn grapheme_iter_at_index<'a>(&'a self, index: usize) -> RopeGraphemeIter<'a> {
let (grapheme_i, mut chunk_iter) = self.chunk_iter_at_index(index);
// Create the grapheme iter for the current node
let mut giter = if let Some(text) = chunk_iter.next() {
text.as_slice().graphemes(true)
}
else {
unreachable!()
};
// Get to the right spot in the iter
for _ in grapheme_i..index {
giter.next();
}
// Create the rope grapheme iter
return RopeGraphemeIter {
chunk_iter: chunk_iter,
cur_chunk: giter,
};
}
//================================================================
// Private utility functions
//================================================================
fn is_leaf(&self) -> bool {
if let RopeData::Leaf(_) = self.data {
true
}
else {
false
}
}
/// Non-recursively updates the stats of a node
fn update_stats(&mut self) {
match self.data {
RopeData::Leaf(ref text) => {
self.grapheme_count_ = grapheme_count(text);
self.tree_height = 1;
},
RopeData::Branch(ref left, ref right) => {
self.grapheme_count_ = left.grapheme_count_ + right.grapheme_count_;
self.tree_height = max(left.tree_height, right.tree_height) + 1;
}
}
}
/// Splits a leaf node into pieces if it's too large
// TODO: find a way to do this that's more algorithmically efficient
// if lots of splits need to happen. This version ends up re-scanning
// the text quite a lot, as well as doing quite a few unnecessary
// allocations.
fn split_if_too_large(&mut self) {
if self.grapheme_count_ > MAX_NODE_SIZE && self.is_leaf() {
// Calculate split position and how large the left and right
// sides are going to be
let split_pos = self.grapheme_count_ / 2;
let new_gc_l = split_pos;
let new_gc_r = self.grapheme_count_ - split_pos;
// Do the split
let mut nl = Box::new(Rope::new());
let mut nr = Box::new(Rope::new());
mem::swap(self, &mut (*nl));
if let RopeData::Leaf(ref mut text) = nl.data {
nr.data = RopeData::Leaf(split_string_at_grapheme_index(text, split_pos));
text.shrink_to_fit();
}
// Recursively split
nl.grapheme_count_ = new_gc_l;
nr.grapheme_count_ = new_gc_r;
nl.split_if_too_large();
nr.split_if_too_large();
// Update the new left and right node's stats
nl.update_stats();
nr.update_stats();
// Create the new branch node with the new left and right nodes
self.data = RopeData::Branch(nl, nr);
self.update_stats();
}
}
/// Merges a non-leaf node into a leaf node if it's too small
fn merge_if_too_small(&mut self) {
if self.grapheme_count_ < MIN_NODE_SIZE && !self.is_leaf() {
let mut merged_text = String::new();
if let RopeData::Branch(ref mut left, ref mut right) = self.data {
// First, recursively merge the children
left.merge_if_too_small();
right.merge_if_too_small();
// Then put their text into merged_text
if let RopeData::Leaf(ref mut text) = left.data {
mem::swap(&mut merged_text, text);
}
if let RopeData::Leaf(ref mut text) = right.data {
merged_text.push_str(text.as_slice());
}
}
// Make this a leaf node with merged_text as its data
self.data = RopeData::Leaf(merged_text);
self.tree_height = 1;
// Don't need to update grapheme count, because it should be the
// same as before.
}
}
/// Rotates the tree under the node left
fn rotate_left(&mut self) {
let mut temp = Rope::new();
if let RopeData::Branch(_, ref mut right) = self.data {
mem::swap(&mut temp, &mut (**right));
if let RopeData::Branch(ref mut left, _) = temp.data {
mem::swap(&mut (**left), &mut (**right));
}
else {
panic!("Rope::rotate_left(): attempting to rotate node without branching right child.");
}
}
else {
panic!("Rope::rotate_left(): attempting to rotate leaf node.");
}
if let RopeData::Branch(ref mut left, _) = temp.data {
mem::swap(&mut (**left), self);
left.update_stats();
}
mem::swap(&mut temp, self);
self.update_stats();
}
/// Rotates the tree under the node right
fn rotate_right(&mut self) {
let mut temp = Rope::new();
if let RopeData::Branch(ref mut left, _) = self.data {
mem::swap(&mut temp, &mut (**left));
if let RopeData::Branch(_, ref mut right) = temp.data {
mem::swap(&mut (**right), &mut (**left));
}
else {
panic!("Rope::rotate_right(): attempting to rotate node without branching left child.");
}
}
else {
panic!("Rope::rotate_right(): attempting to rotate leaf node.");
}
if let RopeData::Branch(_, ref mut right) = temp.data {
mem::swap(&mut (**right), self);
right.update_stats();
}
mem::swap(&mut temp, self);
self.update_stats();
}
/// Balances the tree under this node
fn rebalance(&mut self) {
loop {
let mut rot: isize;
if let RopeData::Branch(ref mut left, ref mut right) = self.data {
let height_diff = (left.tree_height as isize) - (right.tree_height as isize);
// Left side higher than right side
if height_diff > 1 {
let mut child_rot = false;
if let RopeData::Branch(ref lc, ref rc) = left.data {
if lc.tree_height < rc.tree_height {
child_rot = true;
}
}
if child_rot {
left.rotate_left();
}
rot = 1;
}
// Right side higher then left side
else if height_diff < -1 {
let mut child_rot = false;
if let RopeData::Branch(ref lc, ref rc) = right.data {
if lc.tree_height > rc.tree_height {
child_rot = true;
}
}
if child_rot {
right.rotate_right();
}
rot = -1;
}
// Balanced, stop
else {
break;
}
}
else {
// Leaf node, stop
break;
}
if rot == 1 {
self.rotate_right();
}
else if rot == -1 {
self.rotate_left();
}
}
}
}
// Direct indexing to graphemes in the rope
impl Index<usize> for Rope {
type Output = str;
fn index<'a>(&'a self, index: &usize) -> &'a str {
if *index >= self.grapheme_count() {
panic!("Rope::Index: attempting to fetch grapheme that outside the bounds of the text.");
}
match self.data {
RopeData::Leaf(ref text) => {
let mut i: usize = 0;
for g in text.graphemes(true) {
if i == *index {
return &g;
}
i += 1;
}
unreachable!();
},
RopeData::Branch(ref left, ref right) => {
if *index < left.grapheme_count() {
return &left[*index];
}
else {
return &right[*index - left.grapheme_count()];
}
},
}
}
}
//=============================================================
// Rope iterators
//=============================================================
/// An iterator over a rope's string chunks
pub struct RopeChunkIter<'a> {
node_stack: Vec<&'a Rope>,
}
impl<'a> Iterator for RopeChunkIter<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
if let Some(next_chunk) = self.node_stack.pop() {
loop {
if let Option::Some(node) = self.node_stack.pop() {
match node.data {
RopeData::Leaf(_) => {
self.node_stack.push(node);
break;
},
RopeData::Branch(ref left, ref right) => {
self.node_stack.push(&(**right));
self.node_stack.push(&(**left));
continue;
}
}
}
else {
break;
}
}
if let RopeData::Leaf(ref text) = next_chunk.data {
return Some(text.as_slice());
}
else {
unreachable!();
}
}
else {
return None;
}
}
}
/// An iterator over a rope's graphemes
pub struct RopeGraphemeIter<'a> {
chunk_iter: RopeChunkIter<'a>,
cur_chunk: Graphemes<'a>,
}
impl<'a> Iterator for RopeGraphemeIter<'a> {
type Item = &'a str;
fn next(&mut self) -> Option<&'a str> {
loop {
if let Some(g) = self.cur_chunk.next() {
return Some(g);
}
else {
if let Some(s) = self.chunk_iter.next() {
self.cur_chunk = s.graphemes(true);
continue;
}
else {
return None;
}
}
}
}
}
//===================================================================
// Unit test
//===================================================================
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn new_1() {
let rope = Rope::new();
let mut iter = rope.grapheme_iter();
assert_eq!(None, iter.next());
}
#[test]
fn new_2() {
let rope = Rope::new_from_str("Hello world!");
let mut iter = rope.grapheme_iter();
assert_eq!(Some("H"), iter.next());
assert_eq!(Some("e"), iter.next());
assert_eq!(Some("l"), iter.next());
assert_eq!(Some("l"), iter.next());
assert_eq!(Some("o"), iter.next());
assert_eq!(Some(" "), iter.next());
assert_eq!(Some("w"), iter.next());
assert_eq!(Some("o"), iter.next());
assert_eq!(Some("r"), iter.next());
assert_eq!(Some("l"), iter.next());
assert_eq!(Some("d"), iter.next());
assert_eq!(Some("!"), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn new_3() {
let s = String::from_str("Hello world!");
let rope = Rope::new_from_string(s);
let mut iter = rope.grapheme_iter();
assert_eq!(Some("H"), iter.next());
assert_eq!(Some("e"), iter.next());
assert_eq!(Some("l"), iter.next());
assert_eq!(Some("l"), iter.next());
assert_eq!(Some("o"), iter.next());
assert_eq!(Some(" "), iter.next());
assert_eq!(Some("w"), iter.next());
assert_eq!(Some("o"), iter.next());
assert_eq!(Some("r"), iter.next());
assert_eq!(Some("l"), iter.next());
assert_eq!(Some("d"), iter.next());
assert_eq!(Some("!"), iter.next());
assert_eq!(None, iter.next());
}
#[test]
fn index() {
let rope = Rope::new_from_str("Hel世界lo world!");
assert_eq!("H", &rope[0]);
assert_eq!("", &rope[4]);
}
#[test]
fn to_string() {
let rope = Rope::new_from_str("Hello there good people of the world!");
let s = rope.to_string();
assert_eq!("Hello there good people of the world!", s.as_slice());
}
#[test]
fn split_1() {
let mut rope1 = Rope::new_from_str("Hello there good people of the world!");
let rope2 = rope1.split(18);
assert_eq!("Hello there good p", rope1.to_string().as_slice());
assert_eq!("eople of the world!", rope2.to_string().as_slice());
}
#[test]
fn split_2() {
let mut rope1 = Rope::new_from_str("Hello there good people of the world!");
let rope2 = rope1.split(37);
assert_eq!("Hello there good people of the world!", rope1.to_string().as_slice());
assert_eq!("", rope2.to_string().as_slice());
}
#[test]
fn split_3() {
let mut rope1 = Rope::new_from_str("Hello there good people of the world!");
let rope2 = rope1.split(0);
assert_eq!("", rope1.to_string().as_slice());
assert_eq!("Hello there good people of the world!", rope2.to_string().as_slice());
}
#[test]
fn append_1() {
let mut rope1 = Rope::new_from_str("Hello there good p");
let rope2 = Rope::new_from_str("eople of the world!");
rope1.append(rope2);
assert_eq!("Hello there good people of the world!", rope1.to_string().as_slice());
}
#[test]
fn append_2() {
let mut rope1 = Rope::new_from_str("Hello there good people of the world!");
let rope2 = Rope::new_from_str("");
rope1.append(rope2);
assert_eq!("Hello there good people of the world!", rope1.to_string().as_slice());
}
#[test]
fn append_3() {
let mut rope1 = Rope::new_from_str("");
let rope2 = Rope::new_from_str("Hello there good people of the world!");
rope1.append(rope2);
assert_eq!("Hello there good people of the world!", rope1.to_string().as_slice());
}
#[test]
fn insert_text() {
let mut rope = Rope::new();
rope.insert_text_at_grapheme_index("Hello 世界!", 0);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 9);
assert!(Some("H") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some(" ") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("!") == iter.next());
assert!(None == iter.next());
}
#[test]
fn insert_text_in_non_empty_buffer_1() {
let mut rope = Rope::new_from_str("Hello\n 世界\r\n!");
rope.insert_text_at_grapheme_index("Again ", 0);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 17);
assert!(Some("A") == iter.next());
assert!(Some("g") == iter.next());
assert!(Some("a") == iter.next());
assert!(Some("i") == iter.next());
assert!(Some("n") == iter.next());
assert!(Some(" ") == iter.next());
assert!(Some("H") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some(" ") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("\r\n") == iter.next());
assert!(Some("!") == iter.next());
assert!(None == iter.next());
}
#[test]
fn insert_text_in_non_empty_buffer_2() {
let mut rope = Rope::new_from_str("Hello\n 世界\r\n!");
rope.insert_text_at_grapheme_index(" again", 5);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 17);
assert!(Some("H") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some(" ") == iter.next());
assert!(Some("a") == iter.next());
assert!(Some("g") == iter.next());
assert!(Some("a") == iter.next());
assert!(Some("i") == iter.next());
assert!(Some("n") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some(" ") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("\r\n") == iter.next());
assert!(Some("!") == iter.next());
assert!(None == iter.next());
}
#[test]
fn insert_text_in_non_empty_buffer_3() {
let mut rope = Rope::new_from_str("Hello\n 世界\r\n!");
rope.insert_text_at_grapheme_index("again", 6);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 16);
assert!(Some("H") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("a") == iter.next());
assert!(Some("g") == iter.next());
assert!(Some("a") == iter.next());
assert!(Some("i") == iter.next());
assert!(Some("n") == iter.next());
assert!(Some(" ") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("\r\n") == iter.next());
assert!(Some("!") == iter.next());
assert!(None == iter.next());
}
#[test]
fn insert_text_in_non_empty_buffer_4() {
let mut rope = Rope::new_from_str("Hello\n 世界\r\n!");
rope.insert_text_at_grapheme_index("again", 11);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 16);
assert!(Some("H") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some(" ") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("\r\n") == iter.next());
assert!(Some("!") == iter.next());
assert!(Some("a") == iter.next());
assert!(Some("g") == iter.next());
assert!(Some("a") == iter.next());
assert!(Some("i") == iter.next());
assert!(Some("n") == iter.next());
assert!(None == iter.next());
}
#[test]
fn insert_text_in_non_empty_buffer_5() {
let mut rope = Rope::new_from_str("Hello\n 世界\r\n!");
rope.insert_text_at_grapheme_index("again", 2);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 16);
assert!(Some("H") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("a") == iter.next());
assert!(Some("g") == iter.next());
assert!(Some("a") == iter.next());
assert!(Some("i") == iter.next());
assert!(Some("n") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some(" ") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("\r\n") == iter.next());
assert!(Some("!") == iter.next());
assert!(None == iter.next());
}
#[test]
fn insert_text_in_non_empty_buffer_6() {
let mut rope = Rope::new_from_str("Hello\n 世界\r\n!");
rope.insert_text_at_grapheme_index("again", 8);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 16);
assert!(Some("H") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some(" ") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("a") == iter.next());
assert!(Some("g") == iter.next());
assert!(Some("a") == iter.next());
assert!(Some("i") == iter.next());
assert!(Some("n") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("\r\n") == iter.next());
assert!(Some("!") == iter.next());
assert!(None == iter.next());
}
#[test]
fn insert_text_in_non_empty_buffer_7() {
let mut rope = Rope::new_from_str("Hello\n 世界\r\n!");
rope.insert_text_at_grapheme_index("\nag\n\nain\n", 2);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 20);
assert!(Some("H") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("a") == iter.next());
assert!(Some("g") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("a") == iter.next());
assert!(Some("i") == iter.next());
assert!(Some("n") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some(" ") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("") == iter.next());
assert!(Some("\r\n") == iter.next());
assert!(Some("!") == iter.next());
assert!(None == iter.next());
}
#[test]
fn remove_text_1() {
let mut rope = Rope::new_from_str("Hi\nthere\npeople\nof\nthe\nworld!");
rope.remove_text_between_grapheme_indices(0, 3);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 26);
assert!(Some("t") == iter.next());
assert!(Some("h") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("r") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("p") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("p") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("f") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("t") == iter.next());
assert!(Some("h") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("w") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("r") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("d") == iter.next());
assert!(Some("!") == iter.next());
assert!(None == iter.next());
}
#[test]
fn remove_text_2() {
let mut rope = Rope::new_from_str("Hi\nthere\npeople\nof\nthe\nworld!");
rope.remove_text_between_grapheme_indices(0, 12);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 17);
assert!(Some("p") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("f") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("t") == iter.next());
assert!(Some("h") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("w") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("r") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("d") == iter.next());
assert!(Some("!") == iter.next());
assert!(None == iter.next());
}
#[test]
fn remove_text_3() {
let mut rope = Rope::new_from_str("Hi\nthere\npeople\nof\nthe\nworld!");
rope.remove_text_between_grapheme_indices(5, 17);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 17);
assert!(Some("H") == iter.next());
assert!(Some("i") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("t") == iter.next());
assert!(Some("h") == iter.next());
assert!(Some("f") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("t") == iter.next());
assert!(Some("h") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("w") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("r") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("d") == iter.next());
assert!(Some("!") == iter.next());
assert!(None == iter.next());
}
#[test]
fn remove_text_4() {
let mut rope = Rope::new_from_str("Hi\nthere\npeople\nof\nthe\nworld!");
rope.remove_text_between_grapheme_indices(23, 29);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 23);
assert!(Some("H") == iter.next());
assert!(Some("i") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("t") == iter.next());
assert!(Some("h") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("r") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("p") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("p") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("f") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("t") == iter.next());
assert!(Some("h") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("\n") == iter.next());
assert!(None == iter.next());
}
#[test]
fn remove_text_5() {
let mut rope = Rope::new_from_str("Hi\nthere\npeople\nof\nthe\nworld!");
rope.remove_text_between_grapheme_indices(17, 29);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 17);
assert!(Some("H") == iter.next());
assert!(Some("i") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("t") == iter.next());
assert!(Some("h") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("r") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("p") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("p") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("o") == iter.next());
assert!(None == iter.next());
}
#[test]
fn remove_text_6() {
let mut rope = Rope::new_from_str("Hello\nworld!");
rope.remove_text_between_grapheme_indices(3, 12);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 3);
assert!(Some("H") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("l") == iter.next());
assert!(None == iter.next());
}
#[test]
fn remove_text_7() {
let mut rope = Rope::new_from_str("Hi\nthere\nworld!");
rope.remove_text_between_grapheme_indices(5, 15);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 5);
assert!(Some("H") == iter.next());
assert!(Some("i") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("t") == iter.next());
assert!(Some("h") == iter.next());
assert!(None == iter.next());
}
#[test]
fn remove_text_8() {
let mut rope = Rope::new_from_str("Hello\nworld!");
rope.remove_text_between_grapheme_indices(3, 11);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 4);
assert!(Some("H") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("!") == iter.next());
assert!(None == iter.next());
}
#[test]
fn remove_text_9() {
let mut rope = Rope::new_from_str("Hello\nworld!");
rope.remove_text_between_grapheme_indices(8, 12);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 8);
assert!(Some("H") == iter.next());
assert!(Some("e") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("l") == iter.next());
assert!(Some("o") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("w") == iter.next());
assert!(Some("o") == iter.next());
assert!(None == iter.next());
}
#[test]
fn remove_text_10() {
let mut rope = Rope::new_from_str("12\n34\n56\n78");
rope.remove_text_between_grapheme_indices(4, 11);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 4);
assert!(Some("1") == iter.next());
assert!(Some("2") == iter.next());
assert!(Some("\n") == iter.next());
assert!(Some("3") == iter.next());
assert!(None == iter.next());
}
#[test]
fn remove_text_11() {
let mut rope = Rope::new_from_str("1234567890");
rope.remove_text_between_grapheme_indices(9, 10);
let mut iter = rope.grapheme_iter();
assert!(rope.grapheme_count() == 9);
assert!(Some("1") == iter.next());
assert!(Some("2") == iter.next());
assert!(Some("3") == iter.next());
assert!(Some("4") == iter.next());
assert!(Some("5") == iter.next());
assert!(Some("6") == iter.next());
assert!(Some("7") == iter.next());
assert!(Some("8") == iter.next());
assert!(Some("9") == iter.next());
assert!(None == iter.next());
}
}
#[cfg(test)]
mod benches {
use super::*;
use test::Bencher;
#[bench]
fn new_from_str_1(b: &mut Bencher) {
b.iter(|| {
let _ = Rope::new_from_str("
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
});
}
#[bench]
fn new_from_str_2(b: &mut Bencher) {
b.iter(|| {
let _ = Rope::new_from_str("
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
});
}
#[bench]
fn new_from_str_3(b: &mut Bencher) {
b.iter(|| {
let _ = Rope::new_from_str("
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
});
}
#[bench]
fn new_from_str_4(b: &mut Bencher) {
b.iter(|| {
let rope = Rope::new_from_str("
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
});
}
#[bench]
fn insert_text_bench_1(b: &mut Bencher) {
b.iter(|| {
let mut rope = Rope::new();
for _ in 0..200 {
rope.insert_text_at_grapheme_index("Hi", 0);
}
});
}
#[bench]
fn insert_text_bench_2(b: &mut Bencher) {
b.iter(|| {
let mut rope = Rope::new();
for i in 0..200 {
rope.insert_text_at_grapheme_index("Hi", i/2);
}
});
}
#[bench]
fn insert_text_bench_3(b: &mut Bencher) {
b.iter(|| {
let mut rope = Rope::new();
for i in 0..200 {
rope.insert_text_at_grapheme_index("Hi", i);
}
});
}
#[bench]
fn remove_text_bench_1(b: &mut Bencher) {
b.iter(|| {
let mut rope = Rope::new_from_str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
for _ in 0..200 {
rope.remove_text_between_grapheme_indices(0, 2);
}
});
}
#[bench]
fn remove_text_bench_2(b: &mut Bencher) {
b.iter(|| {
let mut rope = Rope::new_from_str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
for i in 0..200 {
rope.remove_text_between_grapheme_indices((200-i)-1, (200-i)+1);
}
});
}
#[bench]
fn remove_text_bench_3(b: &mut Bencher) {
b.iter(|| {
let mut rope = Rope::new_from_str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa");
for i in 0..200 {
rope.remove_text_between_grapheme_indices(400-(i*2)-2, 400-(i*2));
}
});
}
}