HackerReposA FIELD GUIDE TO OPEN SOURCE
ProSponsor the shelf♧ 0
← Back to top all-time
josephg
jumprope-rs
Rust2022–2026
josephg / jumprope-rs

jumprope-rs

Discover this repository through its Hacker News conversations.

2Distinct people
8Mentions
0Explicit recommenders
152GitHub stars
REPOSITORY AT A GLANCE

What to know before exploring

What it is

A public description has not been verified.

Where it is used

No documented product use has been verified yet.

What people are saying

No recommendation phrase was found in the indexed comments.

No classified warning is attached to this page. Read the discussions before treating silence as approval.

Also in these discussions

Mentioned in the same Hacker News threads. That is not proof they are substitutes.

This week on Hacker News

Nov 7–Nov 14 UTC · Direct repository links and separately labeled related project stories. Indexed through 11/14/2026, 5:04:57 PM UTC.

No direct repository links were found in the indexed HN discussions over the past seven days. Older discussions are available below.

Mentions over time

HN mentions by year8 dated mentions

Observed mentions: 2022-08-09 00:48:36 UTC to 2026-06-16 02:32:00 UTC.

012342022-01-01 00:00:00 UTC to 2023-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments20222023-01-01 00:00:00 UTC to 2024-01-01 00:00:00 UTC (exclusive): 4 mentions; 0 submissions, 4 comments2024-01-01 00:00:00 UTC to 2025-01-01 00:00:00 UTC (exclusive): 0 mentions; 0 submissions, 0 comments20242025-01-01 00:00:00 UTC to 2026-01-01 00:00:00 UTC (exclusive): 2 mentions; 0 submissions, 2 comments2026-01-01 00:00:00 UTC to 2027-01-01 00:00:00 UTC (exclusive): 1 mentions; 0 submissions, 1 comments. Incomplete calendar period.2026*

* An incomplete calendar period is marked with an outlined bar. Its count is not directly comparable with a full period.

Counts come from the repository’s dated source evidence. Index cutoff: 2026-11-02 08:16:59 UTC.

View mention counts and date ranges
UTC ranges include their start and exclude their end. Select a period to filter the source evidence.
PeriodStart (UTC)End (exclusive, UTC)MentionsSubmissionsComments
20222022-01-01 00:00:00 UTC2023-01-01 00:00:00 UTC101
20232023-01-01 00:00:00 UTC2024-01-01 00:00:00 UTC404
20242024-01-01 00:00:00 UTC2025-01-01 00:00:00 UTC000
20252025-01-01 00:00:00 UTC2026-01-01 00:00:00 UTC202
2026 (partial)2026-01-01 00:00:00 UTC2027-01-01 00:00:00 UTC101

What Hacker News says

8 sources
> Until Rust has equal meta-programming support to C++ it's always going to be "slower". What metaprogramming does C++ have that rust is lacking? If you need more than traits + generics, rust also has proc macros. Proc macros are essentially portable compiler extensions. They take in a stream of symbols from the user's program at compile time and emit rust code that gets passed straight to the compiler. You lose out on syntax highlighting and they make compilation slower. But macros are essentially compile-time code gen. They work great. In rust, you can do things like JSX at compile-time without any special compiler support. (See: leptos.) > Realistically the difference doesn't matter much and if you're writing code that must be as fast as possible your writing unsafe Rust that looks a lot more like C/C++ then anything Rust. I agree that
Read the rest
the difference is small in practice. Good rust often does look a lot like C - with plain structs everywhere and lots of global-ish scoped functions. But I don't agree about unsafe. I've spent some time porting well optimised code from C to rust. I generally find I need far less unsafe code than I expected. I ported a ~500 line skip list implementation from C to rust a few years ago. I think my rust code ended up using just 2 unsafe functions. The rest of the code didn't need any unsafe at all. My skip list was a monster to debug in C because most logic bugs ended up corrupting memory. As a result, a bug in one function caused crashes in far away code. In rust, debugging was much easier. There wasn't any "spooky action at a distance". And that let me reason about the code much more easily. As a result, once I got it working I ended up adding a few more optimisations in rust that I was too overwhelmed to write in C. The rust code is now ~2-3x faster. If you're interested: https://github.com/josephg/jumprope-rs#benchmarks C code is here: https://github.com/josephg/librope
In How memory safety CVEs differ between Rust and C/C++
> Both Option and Result can be unwrapped and - to some extent not coincidentally - both can also be subject to the Try operator (?) which is arguably more correct here than unwrap because this can fail and perhaps the caller will have some plan to recover. I guess its equivalent to Go code like this: value, err := stuff() if err != nil { panic(err) } Or in C: int result = stuff(); assert(result >= 0); If someone wrote code like that and the program crashed, nobody would attack Go or C. In all these cases (including rust), the programmer is expressing clear, explicit intent for the program to panic if the call failed. I've seen some people say .unwrap() should be named .unwrap_or_panic() or something to make that more clear? I dunno. It seems like a nothingburger to me. A buggy program crashed. They'll do tha
Read the rest
t. > What sort of "interacting with raw pointers" are you thinking of that's too inconvenient and ugly for your liking? I have 2 complaints. First, I wish Rust had a -> operator or something like it. This sort of thing is horrible: (*(*(*ptr).foo).bar) Secondly, rust's aliasing rules make writing pointer heavy code very difficult. I like to run my unsafe code through MIRI to make sure I'm not doing anything bad, and its incredibly subtle. Here's an unsafe function which manages the internal state of a skip list: https://github.com/josephg/jumprope-rs/blob/3981256e4e741d8b... This code is insanely fragile. There are multiple pointers to different elements floating around. The only way I got miri to calm down was to dereference the node pointer constantly. Eg: *cursor.num_bytes -= (*node).str.len_bytes(); let next = (*node).first_next().node; Basically everything else I tried caused obscure aliasing problems. I think if I rewrote this code today I'd probably use a Vec and safe rust instead. I can much more confident write correct C code than correct unsafe rust code. I wish it were the other way around. As a general principle, unsafe rust should be as simple and easy to reason about as possible so we can spot security problems. But rust's syntax makes unsafe code very complex. I don't think this complexity is in any way necessary.
In Several core problems with Rust
> When you program with totally unsafe languages, you develop more strategies than just relying on a type checker and borrow checker: RAII, "crash early", TDD, completion-compatible naming conventions, even syntax highlighting (coloring octal numbers differently)... Having written a fair bit of rust and C, I don't consider the tools for safety in C to be good enough. In C, its so easy for small mistakes to turn into CVEs. ASAN and friends help. But they're a long way from perfect. Testing helps. But in C, there's usually a fair bit of time that passes between when I make a mistake and when I discover the bug through testing. Its also so easy for bugs to hide in C in the cracks of UB. One of my clearest experiences with C and rust was a rope library I wrote several years ago. Ropes are "fancy strings". They're strings, but they support O(l
Read the rest
og n) insert & delete, at arbitrary positions. I wrote my library in pure C, implemented on top of a skip list. The code is very subtle - like, there's a lot of very careful logic. A single incorrect line of code will often cause silent data corruption or memory errors that don't show up until much later. It took about as long to properly test & debug the library as it took to write it in the first place. Debugging it was exhausting - there were a myriad of obscure edge cases that I needed fuzzing to track down. When the fuzzer found problems, going from a failing fuzzer trace to a code fix was a big job. Before I started, I had a bunch of optimisations in mind that I wanted to add to the library. But it was so exhausting getting it working at all that I never got around to most of them. Eg I wanted to make each node in the skip list into a gap buffer to reduce memcopies. But implementing that would have required significant code changes - which in turn would have meant a new round of memory bugs and debugging. I never brought myself to do it. At some point I rewrote the library in rust, with liberal use of raw pointers. I made just as many mistakes in the implementation - though the compiler caught a lot of them. The first time I ran it it segfaulted. And I thought "here we go again". But despite using raw pointers, there were only 2 unsafe functions in the whole program. A segfault in rust can only happen from unsafe code. So I took a read of that code - and lo and behold, there was my bug, plain as day. Time to fix: 2 minutes. The library never segfaulted again in all my testing. The first time I benchmarked it it was ~10% faster than the C version. I still have no idea why. It was so much easier to write that a little while later, I put the gap buffer optimisation in. Now the rust library is 2-3x faster than C. In this case, memory safety made my program easier to write. And that resulted in better performance. If anyone is curious, C / rust code is here: https://github.com/josephg/librope https://github.com/josephg/jumprope-rs > BUT. the cultural characteristics of the programmers are only one-quarter of the story. The bigger part is about company culture, and more specifically the availability of programmers. Yeah absolutely. I think this is the biggest downside of rust. Rust is really hard - and painful - to learn. It front loads all the pain. In C, you suffer while debugging. In rust, all that suffering happens while learning the language in the first place. I spent months fighting the borrow checker. And its very demotivating not being able to compile your program at all. Once you understand it, it makes sense. But I think there will always be a limited pool of programmers willing to struggle through. Even chatgpt is bad at rust. It makes all sorts of classic beginner mistakes with lifetimes, and the resulting code often won't compile. Even after pointing out the problem, chatgpt is often unable to correct lifetime bugs.
In Safe C++ proposal is not being continued
Thanks for all the work in bootstrapping this part of the ecosystem! I opened an issue[1] on the memory issue for jumprope. It seems to really come down to the large size of skiplist nodes relative to the text. I did some testing with JumpRopeBuf, but ultimately did not include it because I was comparing things from an "interactive editor" perspective where edits are applied immediately instead of a collaborative/CRDT use case where edits are async. But it did perform very well as you said! I feel like JumpRopeBuf feels similar to a piece table, where edits are stored separately and then joined for reading. [1] https://github.com/josephg/jumprope-rs/issues/5
In Text showdown: Gap Buffers vs. Ropes
I'd add one more tip that I think far more software developers should do: Add unit-level fuzz testing throughout your projects. Fuzzy bois are like assertions on steroids. With large projects you often get modules which have an API boundary, complex internals and clear rules for what correct / incorrect look like. For example, data structures or some complex algorithms. (A-star, or whatever). Every time I have a system like this, I'm now in the habit of writing 3 pieces of code: 1. A function that checks the internal invariants are true. Eg, in a Vec, the allocated length should be >= the current length. In a sorted tree, if you iterate through the items, they're sorted. And children are always >= the internal nodes (or whatever the rules are for your tree). During development, I wrap my state mutators in check() calls. This means I know
Read the rest
instantly if one of my mutating functions has broken something. (This is a godsend for debugging.) 2. A function which randomly exercises the code, in a loop. Eg, if you're writing a hash table, write a function which creates a hash table and randomly inserts and deletes items in a loop for awhile. If you've implemented a search algorithm, generate random data and run searches on it. Most complex algorithms and data structures have simple ways to tell if the return value of a query is correct. So check everything. For example, a sorted tree should contain the same items in the same order as a sorted list. Its just faster. So if you're writing a sorted tree, have your randomizer also maintain a sorted list and then periodically check that the sorted list contains the same items in the same order as your tree. If you're writing A-star, check that an inefficient flood fill search returns the same result. Your randomizer should always be explicitly seeded so when it finds problems you can easily and deterministically reproduce them. 3. A test which calls the randomizer over and over again, and checks all the invariants are correct. When this can run overnight with optimizations enabled, your code is probably ok. There's a bunch of delicate performance balances to strike here - its easy to spend too much CPU time checking your invariants. If you do that, you won't find rare bugs because your test won't run enough times. I often end up with something like this: loop (ideally on all cores) { generate random seed initialize a new Foo for i in 0..100 { randomly make foo more complicated (at first check invariants here) } (then later move invariants here) } Every piece of a large program should be tested like this. And if you can, test your whole program like this too. (Doable for most libraries, databases, compilers, etc. This is much harder for graphics engines or UI code.) I've been doing this for years and I can't remember a single time I set something like this up and didn't find bugs. I'm constantly humbled by how effective fuzzy bois are. This sounds complex, but code like this will usually be much smaller and easier to maintain than a thorough unit testing suite. Here's an example from a rope (complex string) library I maintain. The library lets you insert or delete characters in a string at arbitrary locations. The randomizer loop is here[1]. I make Rope and a String, then in a loop make random changes and then call check() to make sure the contents match and all the internal invariants hold. [1] https://github.com/josephg/jumprope-rs/blob/ae2a3f3c2bc7fc1f... When I first ran this test, it found a handful of bugs in my code. I also ran this same code on a few rust rope libraries in cargo. About half of them fail this test.
In How to Survive Your Project's First 100k Lines
I’d go further and say that writing most software without fuzz testing is insane. Fuzz testing is one of those things they should teach in school. They’re a super useful technique - up there with TDD and it’s a tragedy they aren’t more wildly used. Fuzzers are so good because they find so many bugs relative to programmer effort (lines of code). They’re some of the most efficient testing you can do. If I had to choose between a full test suite and a fuzzer, I’d choose the fuzzer. I use fuzzers whenever I have a self contained “machine” in my code which should have well defined behaviour. For example, a b-tree. I write little custom fuzzers each time. The fuzzing code randomly mutates the data structure and keeps a list of the expected btree content. Then periodically I verify that the list and the btree agree on what should be contained in
Read the rest
side the list. In the project I’m working on at the moment, I have about 6 different fuzzers sprinkled throughout my testing code. (Btree fuzzer, rope fuzzer, file serialisation fuzzer, a few crdt fuzzers, and so on). Writing fuzzers is quite devastating for the ego. Usually the first time I point a fuzzer at my code, even when my code has a lot of tests, the fuzzer throws an assertion failure instantly. “Iteration 2 … the state doesn’t match what was expected”. Getting a fuzzer running all night without finding any bugs is a balm for the soul. The code looks like this, if anyone is curious. Here’s a fuzzer for a rope (fancy string) implementation: https://github.com/josephg/jumprope-rs/blob/master/tests/tes...
In Google's OSS-Fuzz expands fuzz-reward program
Using invariants like this is now my preferred programming style. Almost all of my complex container classes have a dbg_check() method which checks all the internal invariants hold, and panics if not. When testing and debugging, I’ll add calls to dbg_check() after each mutation of my data structure. And then I write a fuzzer which exercises my API in a loop. Each iteration, I check that my invariants still hold. The nice thing about this sort of invariant checking is that it makes it very fast and easy to narrow in on bugs. The crash happens right after a change which made the data invalid, not later when the invalid data is accessed. And a few dozen lines of fuzz testing can find an extraordinary quantity of subtle bugs. It’s remarkable. Devastating for the ego, but remarkable. Edit: Simple dbg_check implementation example: https://githu
Read the rest
In Adding design-by-contract conditions to C++ via a GCC plugin
Yep. A few years ago I implemented a skip list based rope library in C[1], and after learning rust I eventually ported it over[2]. The rust implementation was much less code than the C version. It generated a bigger assembly but it ran 20% faster or so. (I don't know why it ran faster than the C version - this was before the noalias analysis was turned on in the compiler). Its now about 3x faster than C, thanks to some use of clever layered data structures. I could implement those optimizations in C, but I find rust easier to work with. C has advantages, but performance is a bad reason to choose C over rust. In my experience, the runtime bounds checks it adds are remarkably cheap from a performance perspective. And its more than offset by the extra optimizations the rust compiler can do thanks to the extra knowledge the compiler has about
Read the rest
your program. If my experience is anything to go by, naively porting C programs to rust would result in faster code a lot of the time. And I find it easier to optimize rust code compared to C code, thanks to generics and the (excellent) crates ecosystem. If I was optimizing for runtime speed, I'd pick rust over C every time. [1] https://github.com/josephg/librope [2] https://github.com/josephg/jumprope-rs
In The case against a C alternative

MAKE YOURSELF AT HOME

A few shortcuts

/
Search the collection
?
Open this guide
Esc
Close dialogs and navigation

Your saved repositories and interests stay in this browser.