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