Skip to content

Adam Chalmers

Tag: #programming

Video: Error handling

The fourth Rust Club video is up! Every Monday I teach Rust to my coworkers at zoo.dev on video chat. We record the call and put it on YouTube so you can learn too. This week's video is about different ways to handle errors in Rust -- when should you panic and when should you return a Result::Err? And what type should that Result::Err be?

Apologies for the low video quality, starting from next episode we used a better-quality recording system.

Video: Analyzing performance

KittyCAD's third Rust Club video is up! We analyze how fast the demo parser from my [first video][/winnow-basics] is, and find ways to speed it up. We use benchmarks to measure its speed, and flamegraphs to visualize its runtime, to find places we can improve.

Apologies for the low video quality, I didn't know we'd be releasing this to YouTube, so it's just using Zoom's "record screen" feature. Starting from episode 5 we used a better-quality recording system.

Video: Parsing a programming language

KittyCAD's second Rust Club video is up! My [first video][/winnow-basics] covered the Winnow library for parsing text. Today's video shows you a real-world parser example. I'm working on the KittyCAD language (KCL) for designing CAD models, and this reviews the tokenizer and parser I wrote recently.

Apologies for the low video quality, I didn't know we'd be releasing this to YouTube, so it's just using Zoom's "record screen" feature. Starting from episode 5 we used a better-quality recording system.

Video: Parsing text with Winnow

I work at KittyCAD, and every Monday I teach Rust to my coworkers for an hour. We always record them, so that over time we build up an archive of Rust learning videos. Recently I realized we should put some of them on the internet, because other programmers outside KittyCAD might find them helpful too!

This is our first episode, and it's about building parsers with Winnow, a new fork of Nom. I'm a big fan of Nom, and I've written about it a lot. I've been interested in Winnow since it was announced, so here's an hour-long explanation of how to use Winnow.

Apologies for the low video quality, I didn't know we'd be releasing this to YouTube, so it's just using Zoom's "record screen" feature. Future episodes should have higher video quality!

Signals vs. Servers

Say you're running a long-lived program, like a server. Let's say the server needs to read some files from disk, like certificates or keys. Every so often, the certificates change, so your server has to reload them. How do you tell the server to reload those files? The traditional way is to use Unix signals. Your server listens for a particular signal, like SIGUSR1 (user-defined signal #1) or SIGHUP (hangup signal), and can execute whatever code you programmed in when the signal is received. So, your code waits for the appropriate signal, receives it, then reloads the certs.

This approach works fine, but it has some usability problems that came up at work. So, my coworkers have been thinking about better ways to do this. I wanted to blog about one such way, and see if anyone has better ideas.

What are Rust's HTTP extensions?

I learned about extensions when reading the hyper docs. But they also pop up in lots of other Rust web libraries, like http, tonic, and actix-web. So they must be really useful, if so many libraries offer them. But I personally had no idea what they were or how to use them. Today I'm going to explain what extensions really are (a set of values, keyed by type), and how you can use them to pass data between different parts of your web servers (e.g. middleware, routers, and handler functions). I'll give you a real-world example from the gRPC server I'm building at my job.

Parsing bitstreams with Nom

Programming languages generally only manipulate bytes (groups of 8 bits). It can be pretty tricky to manipulate single bits. But sometimes you need to -- for example, a DNS header has some 4-bit numbers, and encodes some boolean flags into single bits. So we really need a way to parse binary data without chunking it up into bytes of 8 bits.

Luckily, Nom can do this! In the last blog post, we learned how to parse text files with Nom. The trick is to start with simple parsers that parse a few characters at a time. Then, using combinators, combine those simple parsers into more complex parsers that can deserialize an entire structured file. We can reuse this approach for parsing binary data too. Let's see how!

Parsing Text with Nom

"Parsing" is turning a stream of raw text or binary into some structured data types, i.e. a Rust type that your code can understand and use. This isn't the textbook definition of parsing, but damnit, this is my blog and my opinion. This tutorial is about nom, my favourite Rust parsing library. It uses a parser combinator approach: you start writing tiny parsers that match, say, a single number or a character. These become building blocks for larger parsers, that match, say, a date or a phone number. By combining many small parsers together, you can build a big parser that decodes a file or stream into nice Rust structs and enums. In this tutorial we'll use Nom to parse the input file to an Advent of Code puzzle.

Pin, Unpin, and why Rust needs them

Using async Rust libraries is usually easy. It's just like using normal Rust code, with a little async or .await here and there. But writing your own async libraries can be hard. The first time I tried this, I got really confused by arcane, esoteric syntax like T: ?Unpin and Pin<&mut Self>. I had never seen these types before, and I didn't understand what they were doing. Now that I understand them, I've written the explainer I wish I could have read back then. In this post, we're gonna learn

  • What Futures are
  • What self-referential types are
  • Why they were unsafe
  • How Pin/Unpin made them safe
  • Using Pin/Unpin to write tricky nested futures