#![cfg_attr( feature = "unstable"
, feature( const_fn
, box_syntax, box_patterns
, conservative_impl_trait
, collections, collections_range
, inclusive_range_syntax
))]
#![cfg_attr( all( test, feature = "unstable")
, feature( test, insert_str) )]
#![cfg_attr( feature = "clippy", feature(plugin) )]
#![cfg_attr( feature = "clippy", plugin(clippy) )]
#![cfg_attr( feature = "clippy", allow(unused_variables, dead_code))]
#[macro_use] extern crate macro_attr;
#[macro_use] extern crate newtype_derive;
#[cfg(feature = "unstable")] extern crate collections;
#[cfg(feature = "unstable")] use collections::range::RangeArgument;
extern crate unicode_segmentation;
use std::cmp;
use std::ops;
use std::convert;
use std::fmt;
use std::string;
use std::iter;
macro_rules! or_zero {
($a: expr, $b: expr) => { if $a > $b { $a - $b } else { 0 } }
}
#[cfg(feature = "tendril")] extern crate tendril;
#[cfg(test)] #[macro_use] extern crate quickcheck;
#[cfg(test)] mod test;
#[cfg(all( test, feature = "unstable"))] mod bench;
mod unicode;
pub mod metric;
use metric::{Measured, Metric};
use self::internals::{Node, NodeLink};
pub use self::slice::{ RopeSlice
};
impl<T> convert::From<T> for Rope
where T: convert::Into<NodeLink> {
#[inline] fn from(that: T) -> Self {
Rope { root: that.into().rebalance() }
}
}
#[derive(Clone, Default)]
pub struct Rope {
root: NodeLink
}
pub trait Split: Sized {
fn split<M>(&self, index: M) -> (Self,Self)
where M: Metric
, Self: Measured<M>;
}
impl<M> Measured<M> for Rope
where M: Metric
, NodeLink: Measured<M>
, String: Measured<M>
{
#[inline] fn to_byte_index(&self, index: M) -> Option<usize> {
self.root.to_byte_index(index)
}
#[inline] fn measure(&self) -> M { self.root.measure() }
#[inline] fn measure_weight(&self) -> M { self.root.measure_weight() }
}
impl fmt::Debug for Rope {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "Rope[\"{}\"] {:?}", self.root, self.root)
}
}
impl fmt::Display for Rope {
#[inline]
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}", self.root)
}
}
#[cfg(feature = "unstable")]
macro_rules! unstable_iters {
( $($(#[$attr:meta])*
pub fn $name:ident$(<$lf:tt>)*(&'a $sel:ident) -> $ty:ty {
$body:expr
})+ ) => { $(
$(#[$attr])*
#[cfg_attr(feature = "clippy", allow(needless_lifetimes))]
pub fn $name$(<$lf>)*(&'a $sel) -> $ty {
$body
}
)+ };
( $($(#[$attr:meta])*
pub fn $name:ident$(<$lf:tt>)*(&'a mut $sel:ident) -> $ty:ty {
$body:expr
})+ ) => { $(
$(#[$attr])*
#[cfg(feature = "unstable")]
#[cfg_attr(feature = "clippy", allow(needless_lifetimes))]
pub fn $name$(<$lf>)*(&'a mut $sel) -> $ty {
$body
}
)+ };
}
#[cfg(not(feature = "unstable"))]
macro_rules! unstable_iters {
( $($(#[$attr:meta])*
pub fn $name:ident$(<$lf:tt>)*(&'a $sel:ident) -> impl Iterator<Item=$ty:ty> + 'a {
$body:expr
})+ ) => ($(
$(#[$attr])*
#[cfg(not(feature = "unstable"))]
#[cfg_attr(feature = "clippy", allow(needless_lifetimes))]
pub fn $name$(<$lf>)*(&'a $sel) -> Box<Iterator<Item=$ty> + 'a> {
Box::new($body)
}
)+);
( $( $(#[$attr:meta])*
pub fn $name:ident$(<$lf:tt>)*(&'a mut $sel:ident) - impl Iterator<Item=$ty:ty> + 'a {
$body:expr
})+ ) => { $({
$(#[$attr])*
#[cfg(not(feature = "unstable"))]
#[cfg_attr(feature = "clippy", allow(needless_lifetimes))]
pub fn $name$(<$lf>)*(&'a mut $sel) -> Box<Iterator<Item=$ty> + 'a> {
Box::new($body)
}
})+
};
}
macro_rules! str_iters {
( $($(#[$attr:meta])* impl $name: ident<$ty: ty> for Node {})+ ) => { $(
unstable_iters! {
$(#[$attr])*
pub fn $name<'a>(&'a self) -> impl Iterator<Item=$ty> + 'a{
self.strings().flat_map(str::$name)
}
}
)+ };
( $($(#[$attr:meta])* impl $name: ident<$ty: ty> for Rope {})+ )=> { $(
unstable_iters! {
$(#[$attr])*
pub fn $name<'a>(&'a self) -> impl Iterator<Item=$ty> + 'a{
self.root.$name()
}
}
)+ }
}
macro_rules! unicode_seg_iters {
( $($(#[$attr:meta])* impl $name: ident for Node { extend })+ ) => { $(
unstable_iters! {
$(#[$attr])*
pub fn $name<'a>(&'a self) -> impl Iterator<Item=&'a str> + 'a {
{ use unicode_segmentation::UnicodeSegmentation;
self.strings()
.flat_map(|s| UnicodeSegmentation::$name(s, true))
}
}
}
)+ };
( $($(#[$attr:meta])* impl $name: ident for Node {} )+ ) => { $(
unstable_iters!{
$(#[$attr])*
pub fn $name<'a>(&'a self) -> impl Iterator<Item=&'a str> + 'a {
{ use unicode_segmentation::UnicodeSegmentation;
self.strings().flat_map(UnicodeSegmentation::$name)
}
}
}
)+ };
( $($(#[$attr:meta])* impl $name: ident<$ty: ty> for Rope {})+ )=> { $(
unstable_iters! {
$(#[$attr])*
pub fn $name<'a>(&'a self) -> impl Iterator<Item=$ty> + 'a {
self.root.$name()
}
}
)+ }
}
mod internals;
mod slice;
impl Rope {
#[inline]
pub fn from_utf8(vec: Vec<u8>) -> Result<Rope, string::FromUtf8Error> {
String::from_utf8(vec).map(Rope::from)
}
#[inline]
pub fn from_utf16(v: &[u16]) -> Result<Rope, string::FromUtf16Error> {
String::from_utf16(v).map(Rope::from)
}
#[inline]
pub unsafe fn from_utf8_unchecked(bytes: Vec<u8>) -> Rope {
Rope::from(String::from_utf8_unchecked(bytes))
}
#[inline] pub fn new() -> Rope { Rope::from(Node::empty()) }
pub fn len(&self) -> usize { self.root.len() }
#[inline] pub fn is_empty(&self) -> bool { self.len() == 0 }
#[inline]
#[inline]
pub fn insert<M>(&self, index: M, ch: char) -> Rope
where M: Metric
, Self: Measured<M>
, NodeLink: Measured<M>
, String: Measured<M>
, str: Measured<M>
{
assert!( index <= self.measure()
, "Rope::insert: index {:?} was > length {:?}"
, index, self.measure());
let mut s = String::new();
s.push(ch);
self.insert_rope(index, &Rope::from(s))
}
#[inline]
#[cfg(feature = "unstable")]
pub fn delete<R, M>(&self, range: R) -> Rope
where R: RangeArgument<M>
, M: Metric
, Rope: Measured<M>
, NodeLink: Measured<M>
, String: Measured<M>
, str: Measured<M>
{
let start = range.start().map(|s| *s)
.unwrap_or_else(|| { M::default() });
let end = range.end().map(|e| *e)
.unwrap_or_else(|| { self.measure() });
assert!( start <= end
, "invalid index! start {:?} > end {:?}", end, start);
let (l, r) = self.root.split(start);
let (_, r) = r.split(end - start);
Rope::from(Node::new_branch(l, r))
}
#[inline]
#[cfg(not(feature = "unstable"))]
pub fn delete<M: Metric>(&self, range: ops::Range<M>) -> Rope
where NodeLink: Measured<M>
, String: Measured<M>
, str: Measured<M>
{
let (l, r) = self.root.split(range.start);
let (_, r) = r.split(range.end - range.start);
Rope::from(Node::new_branch(l, r))
}
#[inline]
pub fn insert_rope<M>(&self, index: M, rope: &Rope) -> Rope
where M: Metric
, Self: Measured<M>
, NodeLink: Measured<M>
, String: Measured<M>
, str: Measured<M>
{
if !rope.is_empty() {
let len = self.measure();
if index.into() == 0 {
self.prepend(rope)
} else if index == len {
self.append(rope)
} else {
let (left, right) = self.root.split(index);
Rope::from(&left + &rope.root + right)
}
} else {
self.clone()
}
}
#[inline]
pub fn insert_str<M>(&self, index: M, s: &str) -> Rope
where M: Metric
, Self: Measured<M>
, NodeLink: Measured<M>
, String: Measured<M>
, str: Measured<M>
{
assert!( index <= self.measure()
, "Rope::insert_str: index {:?} was > length {:?}"
, index, self.measure());
self.insert_rope(index, &s.into())
}
pub fn append(&self, other: &Rope) -> Rope {
if !other.is_empty() {
Rope::from(&self.root + &other.root)
} else {
self.clone()
}
}
pub fn prepend(&self, other: &Rope) -> Rope {
if !other.is_empty() {
Rope::from(&other.root + &self.root)
} else {
self.clone()
}
}
pub fn split<M: Metric>(&self, index: M) -> (Rope, Rope)
where Self: Measured<M>
, NodeLink: Measured<M>
, String: Measured<M>
, str: Measured<M>
{
assert!(index <= self.measure());
let (l, r) = self.root.split(index);
(Rope::from(l), Rope::from(r))
}
#[inline]
#[cfg(any(test, feature = "rebalance"))]
fn rebalance(&mut self) {
if self.is_balanced() {
} else {
}
}
#[inline]
#[cfg(any(test, feature = "rebalance"))]
fn is_balanced(&self) -> bool {
self.root.is_balanced()
}
unstable_iters! {
#[doc="Returns an iterator over all the strings in this `Rope`"]
#[inline]
pub fn strings<'a>(&'a self) -> impl Iterator<Item=&'a str> + 'a {
self.root.strings()
}
#[doc="Returns an iterator over all the lines of text in this `Rope`."]
pub fn lines<'a>(&'a self) -> impl Iterator<Item=RopeSlice<'a>> +'a {
{ use internals::IsLineEnding;
let last_idx = self.len() - 1;
Box::new(self.char_indices()
.filter_map(move |(i, c)|
if c.is_line_ending() { Some(i) }
else if i == last_idx { Some(i + 1) }
else { None })
.scan(0, move |mut l, i| {
let last = *l;
*l = i + 1;
Some(self.slice(last..i))
}))
}
}
}
str_iters! {
#[doc="Returns an iterator over all the bytes in this `Rope`.\n\
\nAs a Rope consists of a sequence of bytes, we can iterate \
through a rope by byte. This method returns such an iterator."]
#[inline]
impl bytes<u8> for Rope {}
#[doc="Returns an iterator over all the characters in this `Rope`.\n\
\nAs a `Rope` consists of valid UTF-8, we can iterate through a \
`Rope` by `char`. This method returns such an iterator. \n\
\nIt's important to remember that `char` represents a Unicode \
Scalar Value, and may not match your idea of what a \
'character' is. Iteration over grapheme clusters may be what \
you actually want."]
#[inline]
impl chars<char> for Rope {}
#[inline]
impl char_indices<(usize, char)> for Rope {}
#[inline]
impl split_whitespace<&'a str> for Rope {}
}
unicode_seg_iters! {
#[doc=
"Returns an iterator over the [grapheme clusters][graphemes] of \
`self`.\n\
[graphemes]: \
http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries\
\n\
The iterator is over the *extended grapheme clusters*; as \
[UAX#29]\
(http://www.unicode.org/reports/tr29/#Grapheme_Cluster_Boundaries)\
recommends extended grapheme cluster boundaries for general \
processing."]
#[inline]
impl graphemes<&'a str> for Rope {}
#[doc=
"Returns an iterator over the words of `self`, separated on \
[UAX#29 word boundaries]\
(http://www.unicode.org/reports/tr29/#Word_Boundaries).\n\n\
Here, \"words\" are just those substrings which, after splitting on\
UAX#29 word boundaries, contain any alphanumeric characters. That \
is, the substring must contain at least one character with the \
[Alphabetic](http://unicode.org/reports/tr44/#Alphabetic) \
property, or with [General_Category=Number]\
(http://unicode.org/reports/tr44/#General_Category_Values)."]
#[inline]
impl unicode_words<&'a str> for Rope {}
#[doc=
"Returns an iterator over substrings of `self` separated on \
[UAX#29 word boundaries]\
(http://www.unicode.org/reports/tr29/#Word_Boundaries). \n\n\
The concatenation of the substrings returned by this function is \
just the original string."]
#[inline]
impl split_word_bounds<&'a str> for Rope {}
}
#[inline]
pub fn grapheme_indices(&self) -> internals::GraphemeIndices {
self.root.grapheme_indices()
}
#[inline]
pub fn split_word_bound_indices(&self) -> internals::UWordBoundIndices {
self.root.split_word_bound_indices()
}
#[inline]
fn bytes_eq<I>(&self, other: I) -> bool
where I: Iterator<Item=u8> {
self.bytes().zip(other).all(|(a, b)| a == b)
}
#[inline]
#[cfg(feature = "unstable")]
pub fn slice<R>(&self, range: R) -> RopeSlice
where R: RangeArgument<usize> {
RopeSlice::new(&self.root, range)
}
#[cfg(not(feature = "unstable"))]
pub fn slice(&self, range: ops::Range<usize>) -> RopeSlice {
RopeSlice::new(&self.root, range)
}
}
impl convert::Into<Vec<u8>> for Rope {
fn into(self) -> Vec<u8> {
unimplemented!()
}
}
impl cmp::Eq for Rope {}
impl cmp::PartialEq for Rope {
#[inline]
fn eq(&self, other: &Rope) -> bool {
if self.len() == other.len() {
self.bytes_eq(other.bytes())
} else {
false
}
}
}
impl cmp::PartialEq<str> for Rope {
#[inline]
fn eq(&self, other: &str) -> bool {
if self.len() == other.len() {
self.bytes_eq(other.bytes())
} else {
false
}
}
}
impl cmp::PartialEq<String> for Rope {
#[inline]
fn eq(&self, other: &String) -> bool {
if self.len() == other.len() {
self.bytes_eq(other.bytes())
} else {
false
}
}
}
impl<'a> ops::Add for &'a Rope {
type Output = Rope;
#[inline] fn add(self, other: Self) -> Rope { self.append(other) }
}
impl ops::Add for Rope {
type Output = Rope;
#[inline] fn add(self, other: Self) -> Rope { self.append(&other) }
}
impl ops::Add<String> for Rope {
type Output = Rope;
#[inline] fn add(self, other: String) -> Rope {
self.append(&Rope::from(other))
}
}
impl<'a, 'b> ops::Add<&'b str> for &'a Rope {
type Output = Rope;
#[inline] fn add(self, other: &'b str) -> Rope {
self.append(&Rope::from(other.to_owned()))
}
}
impl<'a> ops::Add<&'a str> for Rope {
type Output = Rope;
#[inline] fn add(self, other: &'a str) -> Rope {
self.append(&Rope::from(other.to_owned()))
}
}
impl ops::Index<usize> for Rope {
type Output = str;
#[inline]
fn index(&self, i: usize) -> &str {
&self.root[i]
}
}
impl ops::Index<ops::Range<usize>> for Rope {
type Output = str;
fn index(&self, _i: ops::Range<usize>) -> &str {
unimplemented!()
}
}
impl ops::Index<ops::RangeTo<usize>> for Rope {
type Output = str;
fn index(&self, _i: ops::RangeTo<usize>) -> &str {
unimplemented!()
}
}
impl ops::Index<ops::RangeFrom<usize>> for Rope {
type Output = str;
fn index(&self, _i: ops::RangeFrom<usize>) -> &str {
unimplemented!()
}
}
impl ops::IndexMut<ops::Range<usize>> for Rope {
fn index_mut(&mut self, _i: ops::Range<usize>) -> &mut str {
unimplemented!()
}
}
impl ops::IndexMut<ops::RangeTo<usize>> for Rope {
fn index_mut(&mut self, _i: ops::RangeTo<usize>) -> &mut str {
unimplemented!()
}
}
impl ops::IndexMut<ops::RangeFrom<usize>> for Rope {
fn index_mut(&mut self, _i: ops::RangeFrom<usize>) -> &mut str {
unimplemented!()
}
}
impl iter::FromIterator<char> for Rope {
fn from_iter<I>(iter: I) -> Rope
where I: IntoIterator<Item=char> {
let s: String = iter.into_iter().collect();
Rope::from(s)
}
}
impl iter::FromIterator<String> for Rope {
fn from_iter<I>(iter: I) -> Rope
where I: IntoIterator<Item=String> {
iter.into_iter().fold(Rope::new(), |acc, x| acc + x)
}
}
impl iter::FromIterator<Rope> for Rope {
fn from_iter<I>(iter: I) -> Rope
where I: IntoIterator<Item=Rope> {
iter.into_iter().fold(Rope::new(), |acc, x| acc + x)
}
}
impl<'a> iter::FromIterator<&'a char> for Rope {
fn from_iter<I>(iter: I) -> Rope
where I: IntoIterator<Item=&'a char> {
let s: String = iter.into_iter().fold(String::new(), |mut acc, x| {acc.push(*x); acc});
Rope::from(s)
}
}
impl<'a> iter::FromIterator<&'a str> for Rope {
fn from_iter<I>(iter: I) -> Rope
where I: IntoIterator<Item=&'a str> {
iter.into_iter().fold(Rope::new(), |acc, x| acc + x)
}
}