A special rope, designed to work with any data type that is not String

Overview

AnyRope

CI Build Status Latest Release Documentation

AnyRope is an arbitrary data type rope for Rust, designed for similar operations that a rope would do, but targeted at data types that are not text.

Example Usage

An example of where this would be useful is in the tagging of text in a text editor, for example, one may assossiate a rope of text with a rope of tags.

// The tags that will be assossiated with a piece of text, that could be a rope.
struct Tag {
    PrintRed,
    Underline,
    Normal,
    Skip(usize)
}

use Tag::*;
impl any_rope::Measurable for Tag {
    fn width(&self) -> usize {
        match self {
            // The zero here represents the fact that multiple tags may be placed
            // in the same character.
            PrintRed | Underline | Normal => 0,
            // Skip here is an amount of characters with no tags in them.
            Skip(amount) => *amount
        }
    }
}

// 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;
// - Skip 4 characters;
// - Change the rendering back to normal.
let mut tags = any_rope::Rope::from_slice(&[Skip(5), PrintRed, 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.

// An empty range, when used in an inclusive removal will remove all
// 0 width elements in that specific width.
// `Rope::remove_exclusive()` would keep them.
// In this case, that would be `Tag::PrintRed`
tags.remove_inclusive(5..5);
// In place of that `Tag::PrintRed`, we will insert `Tag::Underline`.
tags.insert(5, Underline);

// The AnyRope iterator not only returns the element in question, but also the width
// where it starts.
let mut tags_iter = tags.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. For example, we could have a sequence of [Tag::UnderLine, Tag::PrintRed]
    // in the `Rope`, both of which have a width of 0, allowing one to execute multiple
    // `Tag`s in a single character.
    while let Some((index, tag)) = tags_iter.peek() {
        if *index == cur_index {
            activate_tag(tag);
            tags_iter.next();
        } else {
            break;
        }
    }
    print!("{}", ch);
}

When Should I Use AnyRope?

So far, I haven't found a use for AnyRope, other than text editors, but I'm not discounting the possibility that it may be useful somewhere else.

Features

Concept of widths

The width of the element that implements Measurable can be whatever the end user wants it to be, allowing for great flexibility in how AnyRope could be useful.

Rope slices

AnyRope has rope slices that allow you to work with just parts of a rope, using all the read-only operations of a full rope including iterators and making sub-slices.

Flexible APIs with low-level access

Although AnyRope is intentionally limited in scope, it also provides APIs for efficiently accessing and working with its internal slice chunk representation, allowing additional functionality to be efficiently implemented by client code with minimal overhead.

Thread safe

AnyRope ensures that even though clones share memory, everything is thread-safe. Clones can be sent to other threads for both reading and writing.

Unsafe code

AnyRope uses unsafe code to help achieve some of its space and performance characteristics. Although effort has been put into keeping the unsafe code compartmentalized and making it correct, please be cautious about using AnyRope in software that may face adversarial conditions.

License

AnyRope is licensed under the MIT license (LICENSE.md or http://opensource.org/licenses/MIT)

Contributing

Contributions are absolutely welcome! However, please open an issue or email me to discuss larger changes, to avoid doing a lot of work that may get rejected.

Unless you explicitly state otherwise, any contribution intentionally submitted for inclusion in AnyRope by you will be licensed as above, without any additional terms or conditions.

You might also like...
A crate for converting an ASCII text string or file to a single unicode character

A crate for converting an ASCII text string or file to a single unicode character. Also provides a macro to embed encoded source code into a Rust source file. Can also do the same to Python code while still letting the code run as before by wrapping it in a decoder.

Rust crate for obfuscating string literals.

Obfustring This crate provides a obfuscation macro for string literals. This makes it easy to protect them from common reverse engineering attacks lik

Compact, clone-on-write vector and string.

ecow Compact, clone-on-write vector and string. Types An EcoVec is a reference-counted clone-on-write vector. It takes up two words of space (= 2 usiz

Parses a relative time string and returns a `Duration`

humantime_to_duration A Rust crate for parsing human-readable relative time strings and converting them to a Duration. Features Parses a variety of hu

Idiomatic Rust implementations for various Windows string types (like UNICODE_STRING)
Idiomatic Rust implementations for various Windows string types (like UNICODE_STRING)

nt-string by Colin Finck [email protected] Provides idiomatic Rust implementations for various Windows string types: NtUnicodeString (with NtUnicode

Rust based magic-string with source map chains support

enhanced-magic-string Rust implementation of https://www.npmjs.com/package/magic-string with original sourcemap chain support. license. This project i

replaces fixed-sized string prefixes & whole sections in binaries for fast, debuggable, reproducible builds

Replacing fixed-sized string prefixes in binaries to refix them to their build context Here's the long story about what refix does and why you'd want

Additional Rust collections not found in std::collections

More collections Rust crate with additional collections not found in std::collections. Multimaps Completion Name Behaves like 🟩 🟩 🟨 ⬜️ ⬜️ HashSetMu

📁 A not-so-true-to-life implementation of .env (dot env) for gmod

gmsv_dot_env A not-so-true-to-life implementation of a .env file for gmod. Place a .env at ./garrysmod/.env and any variables set in it will be access

Owner
ahoyiski
ahoyiski
An actors library for Rust and Tokio designed to work with async / await message handlers out of the box.

Akt An actors framework for Rust and Tokio. It is heavily inspired by Actix and right now it has very similar look and feel. The main difference is th

Artyom Kozhemiakin 7 Jan 10, 2023
An expression based data notation, aimed at transpiling itself to any cascaded data notation.

Lala An expression oriented data notation, aimed at transpiling itself to any cascaded data notation. Lala is separated into three components: Nana, L

null 37 Mar 9, 2022
A Rust trait to convert numbers of any type and size to their English representation.

num2english This Rust crate provides the NumberToEnglish trait which can be used to convert any* number to its string representation in English. It us

Travis A. Wagner 6 Mar 8, 2023
Type erased vector. All elements have the same type.

Type erased vector. All elements have the same type. Designed to be type-erased as far as possible - most of the operations does not know about concre

null 7 Dec 3, 2022
Build database expression type checker and vectorized runtime executor in type-safe Rust

Typed Type Exercise in Rust Build database expression type checker and vectorized runtime executor in type-safe Rust. This project is highly inspired

Andy Lok 89 Dec 27, 2022
Rust Vector for large amounts of data, that does not copy when growing, by using full `mmap`'d pages.

Large Vector Rust Vector for large amounts of data, that does not copy when growing, by using full mmap'd pages. Maturity I made ths to learn about mm

Wonko der Verständige 21 Apr 23, 2024
A simple and convenient way to bundle owned data with a borrowing type.

A simple and convenient way to bundle owned data with a borrowing type. The Problem One of the main selling points of Rust is its borrow checker, whic

Dmitry Zamkov 20 Dec 21, 2022
An implementation of a predicative polymorphic language with bidirectional type inference and algebraic data types

Vinilla Lang Vanilla is a pure functional programming language based on System F, a classic but powerful type system. Merits Simple as it is, Vanilla

Zehao Chen 73 Aug 4, 2022
An inline SIMD accelerated hashmap designed for small amount of data.

Small-Map An inline SIMD accelerated hashmap designed for small amount of data. Usage use small_map::SmallMap; // Don't worry about the 16 here. // Wh

ihc童鞋@提不起劲 49 Nov 14, 2023
Simple string matching with questionmark- and star-wildcard operator

wildmatch Match strings against a simple wildcard pattern. Tests a wildcard pattern p against an input string s. Returns true only when p matches the

Armin Becher 38 Dec 18, 2022