Expand description
AnyRope is an arbitrary data rope for Rust.
AnyRope’s Rope<M>
contains elements M
that implement Measurable
, a
trait that assigns an arbitrary “measure” to each element, through the
measure()
function. AnyRope can then use these
“measures” to retrieve and iterate over elements in any given “measure” from
the beginning of the Rope<M>
.
Keep in mind that the “measure” does not correspond to the actual size of a type in bits or bytes, but is instead decided by the implementor, and can be whatever value they want.
The library is made up of four main components:
Rope<M>
: the main rope type.RopeSlice<M>
: an immutable view into part of aRope<M>
.iter
: iterators overRope<M>
/RopeSlice<M>
data.RopeBuilder<M>
: an efficient incrementalRope<M>
builder.
A Basic Example
Let’s say we want create a tagging system that will be applied to text, in which the tags either tell you to print normally, print in red, underline, or skip:
#![feature(generic_const_exprs)]
use std::fs::File;
use std::io::{BufReader, BufWriter};
use any_rope::{Rope, Measurable};
// A simple tag structure that our program can understand.
#[derive(Clone, Copy, PartialEq, Eq)]
enum Tag {
InRed,
UnderLine,
Normal,
// The `usize` in here represents an amount of characters that won't change
// the color of the text.
Skip(usize)
}
impl Measurable for Tag {
type Measure = usize;
fn measure(&self) -> Self::Measure {
match self {
// The coloring tags are only meant to color, not to "move forward".
Tag::InRed | Tag::UnderLine | Tag::Normal => 0,
// The Skip tag represents an amount of characters in which no
// tags are applied.
Tag::Skip(amount) => *amount
}
}
}
use Tag::*;
// An `&str` that will be colored.
let my_str = "This word will be red!";
// Here's what this means:
// - Skip 5 characters;
// - Change the color to red;
// - Start underlining;
// - Skip 4 characters;
// - Change the rendering back to normal.
let my_tagger = Rope::from_slice(&[Skip(5), InRed, UnderLine, Skip(4), Normal]);
// Do note that Tag::Skip only represents characters because we are also iterating
// over a `Chars` iterator, and have chosen to do so.
let mut tags_iter = my_tagger.iter().peekable();
for (cur_index, ch) in my_str.chars().enumerate() {
// The while let loop here is a useful way to activate all tags within the same
// character. Note the sequence of [.., InRed, UnderLine, ..], both of which have
// a measure of 0. This means that both would be triggered before moving on to the next
// character.
while let Some((index, tag)) = tags_iter.peek() {
// The returned index is always the measure where an element began. In this
// case, `tags_iter.peek()` would return `Some((0, Skip(5)))`, and then
// `Some((5, InRed))`.
if *index == cur_index {
activate_tag(tag);
tags_iter.next();
} else {
break;
}
}
print!("{}", ch);
}
An example can be found in the examples
directory, detailing a “search and
replace” functionality for Rope<M>
.
Low-level APIs
AnyRope also provides access to some of its low-level APIs, enabling client
code to efficiently work with a Rope<M>
’s data and implement new
functionality. The most important of those API’s are:
- The
chunk_at_*()
chunk-fetching methods ofRope<M>
andRopeSlice<M>
. - The
Chunks
iterator. - The functions in
slice_utils
for operating on&[M]
slices.
As a reminder, if you notice similarities with the AnyRope crate, it is because this is a heavily modified fork of it.
Modules
- Iterators over a
Rope<M>
’s data.
Structs
- A rope of elements that are
Measurable
. - An efficient incremental
Rope<M>
builder. - An immutable view into part of a
Rope<M>
. - A struct meant for testing and exemplification
Enums
- AnyRope’s error type.
Traits
- A trait defining a comparison that must panic if there is ever ambiguity about the ordering in a given struct.
- A object that has a user defined size, that can be interpreted by a
Rope<M>
.
Functions
Type Aliases
- AnyRope’s result type.