• Home
  • History
  • Annotate
Name Date Size #Lines LOC

..03-May-2022-

benches/H03-May-2022-940777

examples/H03-May-2022-890653

src/H03-May-2022-14,0369,906

tests/H03-May-2022-1,3961,067

.cargo-checksum.jsonH A D03-May-202289 11

.cargo_vcs_info.jsonH A D01-Jan-197074 65

.gitignoreH A D01-Jan-197058 65

CHANGELOG.mdH A D01-Jan-197011.6 KiB293186

Cargo.lockH A D01-Jan-197025.2 KiB1,015904

Cargo.tomlH A D01-Jan-19701.4 KiB6151

Cargo.toml.orig-cargoH A D01-Jan-1970923 4737

LICENSE.mdH A D01-Jan-19701 KiB2016

README.mdH A D01-Jan-19706.2 KiB165118

README.md

1# Ropey
2
3[![CI Build Status][github-ci-img]][github-ci]
4[![Latest Release][crates-io-badge]][crates-io-url]
5[![Documentation][docs-rs-img]][docs-rs-url]
6
7Ropey is a utf8 text rope for Rust, designed to be the backing text-buffer for
8applications such as text editors.  Ropey is fast, robust, and can handle huge
9texts and memory-incoherent edits with ease.
10
11
12## Example Usage
13
14```rust
15// Load a text file.
16let mut text = ropey::Rope::from_reader(
17    File::open("my_great_book.txt")?
18)?;
19
20// Print the 516th line (zero-indexed).
21println!("{}", text.line(515));
22
23// Get the start/end char indices of the line.
24let start_idx = text.line_to_char(515);
25let end_idx = text.line_to_char(516);
26
27// Remove the line...
28text.remove(start_idx..end_idx);
29
30// ...and replace it with something better.
31text.insert(start_idx, "The flowers are... so... dunno.\n");
32
33// Print the changes, along with the previous few lines for context.
34let start_idx = text.line_to_char(511);
35let end_idx = text.line_to_char(516);
36println!("{}", text.slice(start_idx..end_idx));
37
38// Write the file back out to disk.
39text.write_to(
40    BufWriter::new(File::create("my_great_book.txt")?)
41)?;
42```
43
44## When Should I Use Ropey?
45
46Ropey is designed and built to be the backing text buffer for applications
47such as text editors, and its design trade-offs reflect that.  Ropey is good
48at:
49
50- Handling frequent edits to medium-to-large texts.  Even on texts that are
51  multiple gigabytes large, edits are measured in single-digit microseconds.
52- Handling Unicode correctly.  It is impossible to create invalid utf8 through
53  Ropey, and all Unicode line endings are correctly tracked including CRLF.
54- Having flat, predictable performance characteristics.  Ropey will never be
55  the source of hiccups or stutters in your software.
56
57On the other hand, Ropey is _not_ good at:
58
59- Handling texts smaller than a couple of kilobytes or so.  That is to say,
60  Ropey will handle them fine, but Ropey allocates space in kilobyte chunks,
61  which introduces unnecessary bloat if your texts are almost always small.
62- Handling texts that are larger than available memory.  Ropey is an in-memory
63  data structure.
64- Getting the best performance for every possible use-case.  Ropey puts work
65  into tracking both line endings and unicode scalar values, which is
66  performance overhead you may not need depending on your use-case.
67
68Keep this in mind when selecting Ropey for your project.  Ropey is very good
69at what it does, but like all software it is designed with certain
70applications in mind.
71
72
73## Features
74
75### Strong Unicode support
76Ropey's atomic unit of text is
77[Unicode scalar values](https://www.unicode.org/glossary/#unicode_scalar_value)
78(or [`char`](https://doc.rust-lang.org/std/primitive.char.html)s in Rust)
79encoded as utf8.  All of Ropey's editing and slicing operations are done
80in terms of char indices, which prevents accidental creation of invalid
81utf8 data.
82
83Ropey also supports converting between scalar value indices and utf16 code unit indices, for interoperation with external APIs that may still use utf16.
84
85### Line-aware
86
87Ropey knows about line breaks, allowing you to index into and iterate over
88lines of text.
89
90Ropey also recognizes all eight Unicode-specified line breaks:
91line feed, carriage return, carriage return + line feed, vertical tab,
92form feed, next line, line separator, and paragraph separator.
93
94### Rope slices
95
96Ropey has rope slices that allow you to work with just parts of a rope, using
97all the read-only operations of a full rope including iterators and making
98sub-slices.
99
100### Flexible APIs with low-level access
101
102Although Ropey is intentionally limited in scope, it also provides APIs for
103efficiently accessing and working with its internal text chunk
104representation, allowing additional functionality to be efficiently
105implemented by client code with minimal overhead.
106
107### Efficient
108
109Ropey is fast and minimizes memory usage:
110
111- On a recent mobile i7 Intel CPU, Ropey performed over 1.8 million small
112  incoherent insertions per second while building up a text roughly 100 MB
113  large.  Coherent insertions (i.e. all near the same place in the text) are
114  even faster, doing the same task at over 3.3 million insertions per
115  second.
116- Freshly loading a file from disk only incurs about 10% memory overhead.  For
117  example, a 100 MB text file will occupy about 110 MB of memory when loaded
118  by Ropey.
119- Cloning ropes is _extremely_ cheap.  Rope clones share data, so an initial
120  clone only takes 8 bytes of memory.  After that, memory usage will grow
121  incrementally as the clones diverge due to edits.
122
123### Thread safe
124
125Ropey ensures that even though clones share memory, everything is thread-safe.
126Clones can be sent to other threads for both reading and writing.
127
128
129## Unsafe code
130
131Ropey uses unsafe code to help achieve some of its space and performance
132characteristics.  Although effort has been put into keeping the unsafe code
133compartmentalized and making it correct, please be cautious about using Ropey
134in software that may face adversarial conditions.
135
136Auditing, fuzzing, etc. of the unsafe code in Ropey is extremely welcome.
137If you find any unsoundness, _please_ file an issue!  Also welcome are
138recommendations for how to remove any of the unsafe code without introducing
139significant space or performance regressions, or how to compartmentalize the
140unsafe code even better.
141
142
143## License
144
145Ropey is licensed under the MIT license (LICENSE.md or http://opensource.org/licenses/MIT)
146
147
148## Contributing
149
150Contributions are absolutely welcome!  However, please open an issue or email
151me to discuss larger changes, to avoid doing a lot of work that may get
152rejected.
153
154An overview of Ropey's design can be found [here](https://github.com/cessen/ropey/blob/master/design/design.md).
155
156Unless you explicitly state otherwise, any contribution intentionally
157submitted for inclusion in Ropey by you will be licensed as above, without any additional terms or conditions.
158
159[crates-io-badge]: https://img.shields.io/crates/v/ropey.svg
160[crates-io-url]: https://crates.io/crates/ropey
161[github-ci-img]: https://github.com/cessen/ropey/workflows/ci/badge.svg
162[github-ci]: https://github.com/cessen/ropey/actions?query=workflow%3Aci
163[docs-rs-img]: https://docs.rs/ropey/badge.svg
164[docs-rs-url]: https://docs.rs/ropey
165