Join us online via Zoom for lightning talks / show and tell / crates you should know.

Mandelbrot Plotter in Python and WASM via @AndrewHoetker

Presentation Slides: https://ahoetker.github.io/mandelbrot-presentation/#/ Python Package Repo: https://github.com/ahoetker/mandelbrot-rs WASM Repo: https://github.com/ahoetker/mandelbrot-wasm Mandelbrot Common Repo: https://github.com/ahoetker/mandelbrot

Andrew presented on Rust's portability by creating a crate for visualizing the Mandelbrot set and consuming it in WASM and Python packages.

For the Python package, he used pyo3 to generate a native Python module. He then used the module in a Jupyter notebook simply with:

from matplotlib import pyplot as plt
from mandelbrot_rs import generate

image = generate(n=1000, threshold=4, max_steps=50)
plt.imshow(image, cmap="Spectral")
plt.axis("off")
plt.show()

Behind the simplicity of this code is Rust's performance and thread-safety without the need for Python's GIL (Global Interpreter Lock).

For the WASM package, he used wasm-bindgen to create the package. Andrew demonstrated using the power of using CanvasRenderingContext2d, HtmlCanvasElement, and ImageData from websys to allow the Rust-built WASM code to manipulate an HTML Canvas element directly without crossing the FFI (Foreign Function Interface) boundary.

Loading Binary Data for Might and Magic via @mysteriouspants

Chris showed his hobby project for taking data from an old Might and Magic game and loading it into a struct. He was inspired by a crazy Russian dude who did the same thing using Turbo Pascal. While working on the project, he found that Rust's error system helped force him to handle failures and be mindful of where they occurred in the callstack. Compare this to Exceptions in Java which rocket through the callstack. However there are a lot of error crates to choose from.

Andrew recommended using anyhow for binary projects and thiserror in library projects. With anyhow, you can use an anyhow::Result to propagate errors up through all your functions up to where you need to handle it and then match on the error type in one place. Thiserror is kind of like the opposite of anyhow, it provides a convenient derive macro for the std::error::Error trait.

OAuth Authentication and Authorization in twentyfive-stars via @BlaineBublitz

Repo: https://github.com/phated/twentyfive-stars

Blaine added authentication and authorization to his GraphQL server. He wanted his solution to be async, implemented as vanilla as possible. He discovered that it is hard to do async Rust while avoiding the tokio ecosystem. One solution is to fork a bunch of libraries. However, using smol your code can be written to adapt to async-std or tokio. Just wrap your async blocks with smol::run. Do not use smol::block_on as it turns your async operation into a blocking operation which slows it down.

The question arose: why not tokio? The answer is simply because the ecosystem Blaine choose initially used async-std (he picked tide as an HTTP server). So he was locked in. Historically, tokio was built at a time when async Rust was still in development (for years). The tokio team did what they needed to do to make things work. Later on, we had async-std which made some improvements, to which tokio added those improvements and made some of their own. The async Rust world bifricated leading to two different ecosystems. We shouldn't have to buy into one or the other. This is the problem that smol intends to solve (see blog post). Blaine notes that Tide now adopted smal as its async runtime.

He ended up forking the oauth2 crate so that he could make it async and remove the reqwest dependency that it ships with (which again depends on tokio). It would be better if reqwest didn't wind up in the binary. If your library (oauth2 in this case) needs to make network requests, accept a client instead of forcing one on your consumer.

Finally, Blaine demonstrated using field(guard()) macros for locking down mutations:

pub struct PermissionGuard {
    pub permission: Permission,
}

#[async_trait::async_trait]
impl Guard for PermissionGuard {
    async fn check(&self, ctx: &Context<'_>) -> FieldResult<()> {
        let maybe_user = ctx.data_opt::<User>();
        if let Some(user) = maybe_user {
            if user.has_permission(&self.permission) {
                Ok(())
            } else {
                Err("Invalid permissions".into())
            }
        } else {
            Err("Must be authenticated".into())
        }
    }
}

And used in the mutation:

#[field(guard(PermissionGuard(permission = "Permission::CreateWaves")))]
pub async fn add_wave(&self, ctx: &Context<'_>, wave: WaveInput) -> FieldResult<Wave> { ... }

Search Indexers and Processing Large Amounts of Data via @ElioGrieco

Elio is interested in search indexers and tools for processing large amounts of unstructured data. His adventures have turned up the following libraries and projects.

  • linkify is a library for finding links in plain-text.

  • sonic-server is a fast, lightweight, schema-less search backend

  • indradb is a graph database implemented with Rust.

CLI Tools You Should Know

"Because the differences between bsd and gnu find weren't enough, now we have rust utils."

  • Mysterious Pants

Cargo Tree

cargo tree is included in Cargo as of v1.44.0. If you're running an older version, update with rustup update. Cargo tree lets you visualize a crate's dependency graph in a tree-like format

Choose

choose is a Rust-implementation of cut (and sometimes awk). It features negative indexing, reverse ranges, regular expression field separators, and has faster performance than awk.

Exa

exa is a Rust implementation of ls. It includes such features as colorized output, Git awareneness, and tons of options for display and filtering.

Diskus

diskus is a minimal fast, Rust implementation of du -sh. According to the benchmarks, it's anywhere from 2x to 10x faster.

Ripgrep

ripgrep is a line-oriented search tool that recursively searches your current directory for a regex pattern while respecting your gitignore rules.

Fd

fd is a simple, fast, user-friendly Rust implementation of find. It includes such features as colorized output, ignoring .gitignore patterns, unicode-awareness, and more.

Bat

bat is cat with wings. It includes such features as syntax highlighting, git integration, showing non-printable characters, automatic paging, file concatenation, and more.

Broot

broot is a CLI File Commander of sorts. It features compact directory overviews, file manipulation, and quick change-directory, and more.

Hunter

hunter is a similar tool to broot. It features quick actions based on file type, multi-file selection, a minibuffer with completion and file/directory/tab substitution, and more.

Crates You Should Know

  • ndarray: n-dimensional container for general elements and numerics. Akin to Python's numpy
  • anyhow: a trait object based error type for easy idiomatic error handling in Rust applications
  • thiserror: provides a convenient derive macro for the std::error::Error trait
  • linkify: a library for finding links in plain-text