When all these articles featuring Rust as one of the most beloved programming languages came out, I was rather sceptic. Coming from C++ I expected a complex and hard to pick up language. At some point though, curiosity got the better of me and after a bit over a year I have to admit: I am sold. In the near future, I plan to write a bit more about my experience with Rust. To set the stage, I would like to sketch how I ended up using Rust in this post by tracing the evolution of a long-running personal project.
For about three years now, I have been working on a chat bot that combines various productivity tasks. Think a mixture of note taking, bookmarking and habit tracking. I found the chatbot interface to be just flexible enough to support these tasks, while being simple enough to not require too much interface work. In the three years I rewrote the code in three distinct iterations:
- iteration: Telegram frontend & Python backend
- iteration: Telegram frontend & Typescript backend
- iteration: custom Android app in Kotlin & core logic Rust
Owing to the fact, that Python was my primary language at the time, I chose it also when I began this project. To get started quickly, I opted for an existing chatbot platform. Telegram stood out, since it was, maybe still is, the only platform that does not require a server to run a chatbot. It allows you to regularly poll their server for new messages. All other platforms require a server that is reachable by the platform provider. The great advantage of the poll interface is that the bot can run anywhere, as long as out-going HTTP requests are possible.
While the first version worked quite well, at some point the fact that the backend had to be up and running continuously became an issue. It ran on my local machine and every time I travelled I was faced with the decision whether to keep the machine running for a week or loose the bot. Therefore I started to look into running the bot on my phone directly. My research on how to run Python on Android however turned up pretty much empty. Given my past positive experiences with Cordova, I decided to give TypeScript a try. Overall development was smooth and I was pleasantly surprised by the type system. Most of my analysis code was still sitting in Python though and I found myself duplicating a lot of code between the two languages.
At this point I decided to look back into native development, as native libraries can easily be wrapped in high-level languages. In fact whichever language you choose, there is a good chance it is able to interface with native code. At the time I had no experience with Rust and ever impatient I dived in head first with the goal of learning on the job. The start was a bit rocky, but after a bit of time I started to see the benefits and joys of Rust, but more on that in coming posts.
The current architecture is:
- A custom Android app with a bare-bones chat bot interface
- The core bot logic written in Rust and exposed to the App as a native library using JNA
- The data loading and processing written in Rust and wrapped in Python using ctypes. However, I'm thinking about using of using PyO3 here
With all the core functionality written in Rust, I can freely move functions from analysis code to the App and back again. Furthermore, since all code is running natively, performance and memory are great. And if I ever decide to package it into a wep app, I can compile the code using WebAssembly. In fact my initial implementation used a custom WebAssembly interpreter. Performance was a bit rough though and I switched to JNA.
Overall, I am pretty happy with how things turned out. I am also somewhat hopeful that there are no more language changes in store. How to use Rust most effectively, in particular when interfacing with other languages, is still not completely clear to me, but I feel I am making progress. Next, I plan to write a bit more about my experience with Rust using the chat bot project as a backdrop. As always feel free to reach out to me on twitter @c_prohm with feedback or comments.