After writing a library, I feel like I finally understand Rust

118 points Mr-Adult

I have been learning and building fairly simple side projects in Rust over the lasts 9 months or so, but I recently finished a crate/library I've been working on. It's by far the most complex Rust code I've written to date, but it is similar to another library I built for my day job where I work with tree data structures a lot. This time around I had to learn to work around the Rust compiler and ownership system. It was a difficult experience to say the least. There were some things I was able to do in C# that relied on the garbage collector but made the code significantly simpler that the Rust compiler just would not let me do. I think the end result turned out much better than my C# version though.

As background, the library I wrote creates iterators that are able to traverse/walk a tree using for loop/iterator syntax. Since there are 4 tree traversal types: breadth-first and depth-first pre-, in-, and post-order searches, I built iterators for all 4 of these traversal types using a trait that simply tells my library code how to move from one node in the tree to its children. For the most part, the Rust algorithm maps approximately 1-to-1 with my C# algorithm with some language differences that make the code look very different. There are a few complications, but nothing too crazy. The exception, however, came when I started to write some streaming iterators for my library using the streaming-iterator crate. Conceptually what I was trying to do is build iterators for the 4 tree traversal types that return a slice where the elements of the slice are the entire node stack from root to current node in the tree traversal. This turned out to be very complex for the breadth-first traversal. Because I was taking ownership of every node of the tree as it came in, I had to progressively build up and manage my own internal representation of the tree so far as I iterated. The borrow checker only let me call the trait method once per node because it was defined such that it consumed the node in the process. In C#, I was able to just call the trait method multiple times and let the garbage collector deal with the consequences later. This turned into very complex code that I had to whiteboard out for quite a while to get it right.

The good thing about this experience is that I feel like I finally understand Rust and am very proud of the end result! For those interested, tree\_iterators\_rs is my library which is published on crates.io.