Rust Learning and Projects

During the COVID-19 pandemic, I made it a habit to add something to this blog every couple of days. I was busy then (surprise!), I am busy now. What changed? Priorities. The phrase “you have to make time for it” was something that didn’t sit well with me for a number of years. When I first heard the phrase, it was probably in reference to some responsibilities that I had shirked on, thus the negative association. I have come around to truly appreciate the phrase for what it is and use it myself. If I don’t prioritize something, it will not happen. I will fill my time with other things first and whatever task it is will either be forgotten or discarded. I am not discarding a number of things, including this webpage. Eventually, using this page and others, I will organize and collate the important items in my life digitally. This will probably take a long time (probably a lifetime). For now here are a few projects of mine that I would like to showcase over the past few years particularly using the Rust programming language.

Here is my fork of the rustlings project with my solutions as patches applied on the trunk. I added a small bit of CI for Gitlab to ensure that my solutions complete the exercises correctly. I periodically update this by pulling the upstream changes into a staging branch, rebasing my changes onto that branch (fixing any conflicts that appear), making small tweaks to exercises that have been updated, getting CI to pass, then merging into the main branch. This means that I have quite a collection of my own solutions to a number of exercises that test knowledge on the basic components of the Rust programming language.

This project is simply a TCP server that takes messages sent over the socket to the server and resends it to all connected sockets/clients. It is a fun way to spin up a really small chat room really quickly (assuming that you can telnet over your local network and type in all the right ip addresses :-)). I was going to turn this project into something with a small tui (text user interface) but UI is never really my game.

This project was my final project for the intro to operating systems course at University of Massachusetts Amherst. This undergrad course allowed for a project type of your choosing - as long as it was an individual project. Most of this course was done in C and C++. I wanted to do a Rust rewrite of one of the projects, and after some debating on which project could remain as faithful to the original implementation, I decided the filesystems project was a good start. The implemented file system is extraordinarily limited, and a file is used as a proxy for an actual block device, but it does have some of the basic components of filesystems implemented (free block list, inodes, block pointers). It does not implement in its current state many essential features of modern filesystems such as directories, permissions, superblock(s), indirect blocks, journaling, etc. Finally, this project contains multiple layers: extensive documentation, unit/system testing, github ci/cd, and a few other tools. This implementation also attempts to remain on feature parity with the project itself. This cause me to learn about the #[repr(C)] macro in Rust which forces the underlying representation to match that of a C struct. Initially, I got the filesystem to work, but because the Rust representation of data and the C representation of data were no identical, the data written to the proxy block device was different between the two implementations.

I have a few other small project written in Rust that aren’t worth sharing here - either because most of the code was derived from someone/somewhere else or because the project is so incomplete that it does not work/isn’t worth sharing. A good example of this is the two-part project that initial motivated me to learn the Rust programming language: C library of datastructures as presented in CS187, and a C library of algorithms as presented in CS311. These two projects are related to eachother in that I wanted to use the datastructures library in the implementation of the algorithms library. Both I chose to write in C for a few reasons: practice in C, manually managing memory, difficulty, performance. These two projects never came to full fruition, however the datastructures project did make some strides (see libds).

I lost some interest in the project when I started dealing with the dependency injection required for custom types. Say you’re making a binary tree out of char[] types, how do you determine the strings ordinality? The answer is you can’t for every type, at least not within the library. A way to do this is let the user specify their own comparison function and inject that function to be used inside the implementation of the binary tree. This uses functions pointers, “void *” types, and feels a little like bending C to feel more object oriented, all things that were displeasing to me even though they were (maybe) necessary evils. The answer for me here… a language that had a more comprehensive type system while still remaining low-level - thus Rust. Essentially, I wanted to be able to have the power of generics (like C++ templates really), without the horrors of C++. Eventually I will take those projects and resurrect them from the land of C and put them in Rust so that I may work past those barriers I ran into long ago, but for now I have much more pressing tasks to attend to.

The final word on Rust projects I have tried includes some very low level work trying to write something to make a disk image that boots via BIOS and then hangs, a dumb kernel if you will, to learn some of the necessary steps of booting to an operating system. I had a good name for this ‘ferrOS’, probably derived/inspired from ferrous-systems and the work that I’ve seen by folks like phil-opp and japaric. For some time I was following the blog by phil-opp here.

That’s the most complete list of Rust projects and information about them that I can gather for now.

  • Jack