Rust, Wasm, and a new Tattoo

April 29, 2019

tl;dr I made this thing and I’m going to use it to make myself a new tattoo.

It might look something like one of these:

“live/and let/live”
“live/and let/live”
“try/to keep/up”
“try/to keep/up”
“?/aurora/borealis”
“?/aurora/borealis”

I’ve been looking for an excuse to use rust for a project for a while now. I’ve also been thinking I might get a second tattoo soon, so why not tackle both goals at once.

Motivation

I’ve always liked the idea of text encoded into interesting patterns for tattoo designs. 1-2 colour graphic tattoos are up my alley visually, but a lot of the designs are pulled from colonized peoples, and being A Tech Bro With A Tribal Tattoo always put me off the idea.

To avoid a design totally divorced from its original cultural context, I thought a simple graphical text cypher would be a nice way to have a tattoo that was more than just some cool lines.

I made the original dots tool to design my first tattoo while stuck on planes flying back and fourth between California and Toronto for contract jobs. It was scrapped together pretty quickly.

I was hoping to slap something together quickly just as a way to learn rust, but while the initial learning curve for rust is a lot better now than when they had n-different types of pointers, it’s still not 100% straightforward.

The Easy Part

I pretty quickly had the data model for my diagram and a function to render it to an SVG string. Nice! No real complaints about that. The borrow checker is pretty unobtrusive when you’re working with immutable references and producing new values.

Trying to render a UI and virtual_dom_rs

The original dots was written with simple event handlers and pulled a lot of information from annotations in the HTML dom itself. Looking at the api for dealing with js values made it seem really cumbersome.

It looked like pretty much every framework out there was pretty early stages and offering slightly different models. the pitch of lightweight “pay for what you use” code that all the wasm-bindgen based frameworks were making.

At the end of the day, virtual_dom_rs was crashing out during patching under what seemed like they should have been safe circumstances. The internet had nothing to say, and there weren’t any relevant open github issues.

Time to pack it up and move to a slightly less buggy framework

Picking up a framework at random

I picked yew because

Yew was comfortable to work with. It got me to a place where I was actually building interactions quickly but I came up against a few unintuitive problems

As a new user to rust, debugging macros was a major pain point for me. Entire html blocks would light up as erroring whenever there was an error in the macro. I’m assuming the macros don’t have access to type information, because there are a lot of awkward workarounds to deal with handling of types compared to JSX.

Yew seems to be set up to solve some of these problems soon in the future (they have Renderable set up different from Component, and it looks like they’re going to set up some kind of stateless component system which should solve a lot of the issues I’ve been having with it.

Bundle Size

By default, cargo-web builds in dev mode.

![The application built in debug mode is 2.4 MB](https://www.notion.so/signed/https%3A%2F%2Fs3-us-west-2.amazonaws.com%2Fsecure.notion-static.com%2F8c155f7b-d6a4-4a7f-81d1-3e0e18bbaba6%2FUntitled.png)

Building with cargo web deploy --release cutts that immediately to 408k

You can further optimize automatically with wasm-opt from binaryen .

nix-env -iA nixpkgs.binaryen

wasm-opt -Oz \
    -o ./target/deploy/radial_dots_compressed.wasm \
    ./target/deploy/radial_dots.wasm
After optimization steps, the non-gzipped wasm is 256k.
After optimization steps, the non-gzipped wasm is 256k.

The overall size is still an order of magnitude larger than the handwritten js for dots. I think the added complexity of having multiple layers of text made a component library a natural thing to structure my work around.

I’m curious what the bundlesize would have come out to had used a different library as a starting point. I think this whole experience has gotten me interested in the prospect of trying out seed or quasar next, if I can think of something sufficiently small so as to be a good learning project.

Next Up

CI/CD

I spent some time trying to get the project to build with nixpkgs. but cargo-web is out of date in nixpks master, and its dependencies weren’t available when I did the traditional nixpkgs version override.

Export

One of the really nice features I put in the original dots was svg import / export with some additional data added to the saved SVG with the settings for the diagram.

Maybe I’ll get around to doing that. I’ve seen serde used around a lot so if I’m going to be using rust at all I should probably learn its de-facto json library.

Getting a Tattoo

I like a lot of the designs I’ve been getting out of this thing. I think I might go for a mixed illustration + graphical approach to this next one. Leave some negative space in the middle and fill it in with some line-work in a different colour.

“I/know/enough”
“I/know/enough”
“;)/;^)”
“;)/;^)”
“sugar/oh/honey/honey”
“sugar/oh/honey/honey”
Home || Archive