Okay, we’ve got a server and we can ping it. Let’s actually make a simple client, so I don’t have to do funny things with echo any more. Specifically, let’s make a REPL!
Okay, we’ve got a server and we can ping it. Let’s actually make a simple client, so I don’t have to do funny things with echo any more. Specifically, let’s make a REPL!
Following up from Cloning Redis in Rust: RESP [Part 1], we can parse the protocol. So now… let’s do something with it.
The obvious(ish) next step, in my mind? Make a server. It’s all going to be over the network eventually, so it’s either here or storing data. Here it is!
Specifically, my goal is not to build the networking and data structures for this project from scratch. Where there are primitives or libraries that will do something like networking for me, I’m going to use them.
Ergo:
So, how do I write a simple server in Tokio?
Recently, I read through Build Your Own Redis with C/C++. C/C++ are ugly, so let’s run through it in Rust!
My goal: implement some large subset of Redis (both server and client) in Rust. For any features I implement, it should be compatible with Redis off the shelf. I should be able to use their client with my server and their server with my client and it should just work.
No idea if this is going to work out, but it sounds like an interesting problem!
First task: the REdis Serialization Protocol (RESP).
Okay, in Proc Macro Workshop: derive(Builder) [Part 1] we created a derive(Builder)
macro to implement the builder pattern. We created a new *Builder
struct, created methods to set each field in a chain, and allowed some fields to be optional.
So what’s left? (Be sure to start with Part 1 if you haven’t read that!)
Let’s do this!
For a while now, I’ve been using make as my task runner for my blog. make run
to run locally, make deploy
to build and push to GitHub pages.
But… the syntax isn’t great for some things and I’ve been working a lot with Rust. So let’s see what just can do!
While continuing to learn a bit more about macros in Rust (previous post), I really want to move beyond the simple declarative macros and get into something a bit more interesting. Enter procedural macros. In a nutshell, procedural macros in Rust, rather than relying entirely on pattern matching and expansion are fully Rust functions.
They take a specific input (a stream of tokens) and output a specific output (a new stream of tokens), but in between they can do just about anything a full Rust function can do. And what’s better yet… they operate at compile time. And because they operate on tokens (rather than a full AST), you can do things that just aren’t syntactically valid in normal Rust. Things like… variadic functions (a la print!
or var!
) or even crazier things like embedding Python in Rust for … reasons.
Today specifically, I’ve started working through the prod-macro-workshop repo. It’s a series of five examples macros with test cases and some guidance set up to help you get up to speed. I’m going to be working through the first of these: derive(Builder)
. Now don’t get me wrong. I really have no idea what I’m doing, so don’t take this as an example of how to write a macro. But perhaps by writing this out, it will help me learn it better… and if you happen to learn something as well, all the better!
Recently I’ve been wanting to learn more about macros in Rust. It was always one of my favorite parts of Racket, so let’s see what we can do.
In order to do that, I’ve been following the excellent MacroKata series. It goes all the way through, starting with the very basics, adding in literals and expressions, handling repetition, nesting, and finally recursion.
What I really want to talk about those is the one that I found most interesting: curry!
.
Let a Snafu number be a base 5 number with the curious property that in addition to the digits 0, 1, and 2, it has the numbers
-
as-1
and=
as-2
. Sum up a list of Snafu numbers.
Given a map with a series of moving walls (that wrap when the hit the edges of the simulation), calculate the fastest route from the top left to the bottom right.
Implement a cellular automaton with the following rules:
NSWE
, SWEN
, WENS
, ENSW
, NSWE
, …)