RSSAmplifier

Blog

Michael-F-Bryan

Recent content on Michael-F-Bryan

adventures.michaelfbryan.comRSS feed ↗48 posts

Latest posts

gcode 0.7: one parser core for streaming visitors and a thin AST

gcode 0.7.0 is on crates.io . If you have been on 0.6.1 (the last stable line that matched the mental model I shipped years ago), this release will break your build on purpose. That is intentional semver: the crate still parses G-code, but the way you plug into parsing is new. 
 In 0.6 the public surface was built around a command iterator. That was workable, but it sat awkwardly next to what…

Obsidian Tricks: Daily Notes

If you’re new to Personal Knowledge Management, let me share something that took me years to fully appreciate: daily notes are the secret sauce that transforms a collection of random notes into a living, breathing knowledge system . 
 Here’s the thing most people miss when they start with PKM—it’s not about having perfect notes, it’s about connecting your notes to real…

Obsidian Tricks: Entity Notes

An entity is a person, place, or organization that you want to track in your Second Brain . By creating separate notes in your Obsidian vault for each entity and using the power of backlinks, you can create a rich, interconnected knowledge base. 
 
 The Power of Backlinks
 
 
 Link to heading 
 
 
 When you create a dedicated note for an entity like [[Michael…

Obsidian Tricks: The Summary Callout


 The [!summary] callout is a crucial component of an Atomic Note , serving as a concise overview that captures the essence of the note’s content. This section at the beginning of each note helps readers quickly grasp the main concept and decide whether to read further. 
 Feel free to use this article as a prompt to generate your own summary callout 😉 

 
 
 Purpose…

Writing Technical Content That Actually Helps People

I’ve been writing technical content for years, and I’ll be honest - I never really thought about how I was writing it. I just wrote the way I think and communicate naturally. Kind of like a stream-of-consciousness documentary of my problem-solving process. 
 Then I started getting feedback that surprised me. People would say things like “Your explanations actually make…

How I Work

I thought it might be helpful to write down some of the core principles and values that guide my professional life. If you are a colleague, friend, potential employer, or just curious, this might be a good place to start. 

 
 Give me ownership, trust my judgement, keep communication open, and let me focus on building things properly. 
 In return, you’ll get high-quality work,…

Link Time Dependency Injection

Have you ever been in a situation where, because of how the code is structured, it’s practically impossible to inject a dependency into the component that needs it? Even global variables - ubiquitously reviled for their ability to do “spooky action at a distance” - weren’t spooky enough. 
 In this article, I’ll share a technique I discovered while working on a…

Reboot Friendly Projects - Building Systems That Let You Disappear (and Come Back)

You get an idea. You get excited. You start building. 
 Then one day — you stop. 
 No dramatic reason. No catastrophic failure. Just… gone. You forget about it. Or you can’t bear to look at it. Or you move on. And when you do want to come back, you can’t remember what anything meant or why you even cared. 
 This isn’t a lack of discipline. It’s just a…

Embracing a New Chapter: My Farewell to Wasmer and the Journey Ahead


 Introduction
 
 
 Link to heading 
 
 
 My journey at Wasmer has been a profound chapter in my life, filled with both incredible achievements and challenging moments. It’s time for me to share an important decision about my career and the path I’m choosing to embark on. 
 
 The Journey at Wasmer
 
 
 Link to heading 
 
 
…

GitHub Actions can't access private repos? Here's how to fix it

When developing locally, you can add a private GitHub repository to your Rust
crate as a git dependency and cargo should be able to retrieve it
just fine. 
 However, when you push your changes to GitHub and run CI, GitHub Actions can
run into authentication issues when trying to build your crate. 
 This is the error message I was fighting for a good part of today: 
 $ cargo…

Announcing Cargo WAPM

While at Hammer of the Gods, we wrote a lot of Rust code that gets compiled to
WebAssembly for use in our containerization technology, Rune. 
 We have over 30 different processing blocks (chunks of code that can be used in
a data processing pipeline) and as you can imagine, publishing and versioning
each of WebAssembly module manually isn’t practical. For that, we lean on…

Bringing include_dir Into the Modern Era

Way back in mid-2017 I created a crate called include_dir with
a single goal in mind - give users an include_dir!() macro that lets them
embed an entire directory in their binary. 
 By most metrics, we’ve been doing phenomenally well. The crate has received a
fair amount of engagement on GitHub via pull requests and issues, and it has had
over 1 million downloads and 127…

Common Newbie Mistakes and Bad Practices in Rust: Bad Habits

When you are coming to Rust from another language you bring all your previous
experiences with you. 
 Often this is awesome because it means you aren’t learning programming from
scratch! However, you can also bring along bad habits which can lead you down
the wrong rabbit hole or make you write bad code. 

 
 The code written in this article is available on the…

Daily Rust: Iterators

Iterators are part of Rust’s secret sauce. They power things from the humble
for-loop to the elegant iterator chain, but have you ever stopped to think how
they work? 
 Let’s find out more about Rust’s iterators by implementing our own versions of
common iterators and reading the standard library’s source code. 

 
 The code written in this…

Daily Rust: Slice Patterns

Rust 1.26 introduced a nifty little feature called Basic Slice
Patterns which lets you pattern match on slices with a known length. Later on
in Rust 1.42 , this was extended to allow using .. to match on
“everything else”. 
 As features go this may seem like a small addition, but it gives developers an
opportunity to write much more expressive code. 

 
…

Deserializing Binary Data Files in Rust

The other day, someone on the Rust user forums posted a question 
that really nerd-sniped me. They had data generated by a C++ program and were
wanting to load it into a Rust program, but when asked what format the data was
in the author didn’t provide some something like a JSON schema or Protobuf file,
instead they just got the definition for a C struct. 
 A common…

Parsing PDF Documents in Rust

In my spare time I’m a volunteer with my state’s emergency services and we
have our own web app for managing unit-specific things like attendance, vehicle
checks, newsletters, on-call rosters, and so on. 
 It’s actually a really useful tool, but there is one feature that really
annoys me… The list of member contact details is only available as a PDF
and…

FFI-Safe Polymorphism: Thin Trait Objects

A while ago someone posted a question on the Rust User Forums
asking how to achieve polymorphism in a C API and while lots of good
suggestions were made, I’d like to explore my take on things. 
 As a recap, Rust provides two mechanisms for letting you write code which will
work with multiple types. These are 
 
 Static Dispatch , where the compiler will generate…

How I Translate Feature Requests into Code

As part of my previous job I worked on a CAD/CAM package, and a very common
task would be to take a vague feature description, rephrase it as a more
formal software problem, then use computational geometry algorithms to turn
it into code which can be integrated into the overall application. 
 I eventually got quite good at this, so I’m going to write down the system…

Geometric Constraint Solvers Part 1: Algebraic Expressions

A really powerful tool in Computer Aided Design (CAD) is the ability to apply
 “constraints” to your drawing. Constraints are a really powerful tool,
allowing the drafter to declare how parts of their drawing are related, then
letting the CAD program figure out how parameters can be manipulated in such
a way that 
 You can think of a constraint as some sort of…

Writing Non-Trivial Macros in Rust

Macros in Rust tend to have a reputation for being complex and magical, the
likes which only seasoned wizards like @dtolnay can hope to
understand, let alone master. 
 Rust’s declarative macros provide a mechanism for pattern matching on
arbitrary syntax to generate valid Rust code at compile time. I use them all
the time for simple search/replace style operations like…

Rust Closures in FFI

Every now and then when using native libraries from Rust you’ll be asked to
pass a callback across the FFI boundary. The reasons are varied, but often
this might be done to notify the caller when “interesting” things happen, for
injecting logic (see the Strategy Pattern ), or to handle the
result of an asynchronous operation. 
 If this were normal Rust,…

Creating a Robust, Reusable Link-Checker

With over 68,842 downloads, one of my most successful Rust projects is a
nondescript little program called mdbook-linkcheck . This
is a link-checker for mdbook , the tool powering a lot of
documentation in the Rust community, including The Rust Programming
Language and The Rustc Dev Book . 
 As an example of what it looks like, I recently found a couple 
broken links in the…

How I Reverse Engineered the LastPass CLI Tool

A couple days ago I was writing an install script for my dotfiles 
and reached a point where I wanted to grab some secrets (my SSH keys) from my
LastPass vault and copy them to the file system. 
 This is easy enough to do using the browser plugin, or even when working with
their command line tool ( lpass ) in an interactive way, but
I found there was no way to ask lpass which…

Reflections on What Motivates a Person

Motivation is a funny thing. 
 I’m someone who’s productivity levels change wildly depending on my
motivation levels. When I work on something which I’m passionate about or
which interests me on an intellectual level (e.g. computational geometry or
systems programming), I’m routinely 5-10x more productive than my peers. 
 However, if I’m working on…

Line Simplification with Ramer–Douglas–Peucker

The other day I needed to do a fairly routine graphical operation, to
“simplify” a polyline with many points into a simpler polyline which has
roughly the same shape plus or minus some tolerance factor. 
 My actual use case was in sending linear movements to a CNC machine. Drawings
are defined using floating point numbers and can be “accurate” to about…

A Pragmatic Approach To Global State

One of the first things I learned when programming professionally is that
 global variables are bad . We all take it for granted that it’s bad practice
to write code that relies heavily on global state but the other day I was
working with a 3rd party native library, and it reminded why these best
practices come about. 
 There are a couple factors which made this…

I Made A Thing: Markedit

A couple days ago I released markedit , a small crate for editing
unstructured markdown documents. This is a useful enough library that I
thought I’d explain the main ideas behind it and potential use cases. 
 This originally came about when I was at work, preparing our application’s
change log before a release for the umpteenth time (we’ve found the keep…

Creating Interactive Applications While Maintaining Your Sanity

One of the primary reasons computers are so ubiquitous in modern society is
their ability to let humans and software cooperate to achieve a desired goal.
That is, to be interactive. 
 Creating interactive applications can be pretty annoying for a programmer.
Unlike a computer which is predictable and will blindly follow any
instructions given to it, 
 
 Humans are…

Words Are Hard - An Essay on Communicating With Non-Programmers

There’s a well-known saying about the hard problems in computer science, of
which I think this is my favourite variant, 
 There are 2 hard problems in computer science: cache invalidation, naming things, and off-by-1 errors. — Leon Bambrick (@secretGeek) January 1, 2010 
 


 I’ve been writing software long enough to be burned by all three at…

A Thought Experiment: Using the ECS Pattern Outside of Game Engines

It’s been about 6 months since I watched Catherine West’s excellent Using
Rust for Game Development sent me down the Entity-Component-System 
(ECS) rabbit hole, and I thought I’d share some of my findings. 
 I’ve been meaning to write about this for quite a while now but it took a
while to put my thoughts into a cohesive article without throwing…

WebAssembly as a Platform for Abstraction

In a project I’ve been playing around with recently, we’ve encountered the
dilemma where you want to make it easy for users to write their own
application logic using the system but at the same time want to keep that logic
decoupled from the implementation details of whatever platform the
application is running on. 
 If you’ve been programming for any amount…

How to RiiR

In a previous article we’ve talked about how you can avoid
rewriting a library in Rust when you don’t need to. But what about the times
when you really do need to? 
 In most languages you’d need to rewrite the entire library from the ground
up, waiting until the port is almost finished before you can start seeing
results. These sorts of ports tend to be quite…

Implementing ArrayVec Using Const Generics

If you&rsquo;ve ever done much embedded programming in Rust, you&rsquo;ve most probably run&#xA;across the arrayvec crate before. It&rsquo;s awesome. The main purpose&#xA;of the crate is to provide the ArrayVec type, which is essentially like&#xA; Vec<T> from the standard library, but backed by an array instead of some&#xA;memory on the heap. &#xA; One of the problems I ran into while writing the…

Audio Processing for Dummies

In my spare time I&rsquo;m an emergency services volunteer, and one of the tasks our&#xA;unit has is to run the radio network and keep track of what&rsquo;s happening. This&#xA;can be a pretty stressful job, especially when there&rsquo;s lots of radio traffic,&#xA;and it&rsquo;s not unusual to miss words or entire transmissions. &#xA; To help with a personal project that could make the job easier…

How to not RiiR

Once you get past the growing pains of the Borrow Checker and realise Rust&#xA;gives you the power to do things which would be unheard of (or just plain&#xA;dangerous) in other languages, the temptation to Rewrite it in Rust &#xA;can be quite strong. However at best, the temptation to RiiR is unproductive&#xA;(unnecessary duplication of effort), and at worst it can promote the creation&#xA;of…

Working With G-Code

As mentioned in the previous post there are a handful of tasks&#xA;which may be tackled next, but only one of them really allows us to make progress&#xA;towards our goal of implementing the simulated firmware for a 3D Printer. &#xA; Let&rsquo;s send the motion controller some g-code. &#xA; &#xA; Creating Message types&#xA; &#xA; &#xA; Link to heading &#xA; &#xA; &#xA; If we want to send g-code…

Wiring Up Communication

As we mentioned in the last AiMC post , the next task is to wire up&#xA;communications between the simulator&rsquo;s backend and frontend. &#xA; As a general rule, our frontend will have two communication regimes: &#xA; &#xA; When something happens (e.g. a button is pressed or a job starts sending),&#xA;the frontend will send a batch of messages to the backend and interpret the&#xA;response &#xA;…

Plugins in Rust

Imagine you are implementing a calculator application and want users to be able&#xA;to extend the application with their own functionality. For example, imagine a&#xA;user wants to provide a random() function that generates true random numbers&#xA;using random.org instead of the pseudo-random numbers that a crate like&#xA; rand would provide. &#xA; The Rust language gives you a lot of really…

A Better Frontend

Now we&rsquo;ve got a half-usable motion controller, we need a graphical way for&#xA;humans to interact with it. The controller runs in a browser, which makes&#xA; Vue a perfect candidate for the UI. &#xA; &#xA; Adding Vue to the Frontend&#xA; &#xA; &#xA; Link to heading &#xA; &#xA; &#xA; Now, we don&rsquo;t actually have much frontend code (47 lines of JavaScript to be&#xA;exact) so it&rsquo;s…

Initial Motion System

Now we&rsquo;ve got some simple automation code, lets start a proper&#xA; Motion system. &#xA; Most Motion systems are designed around a &ldquo;control mode&rdquo; , a fancy term for&#xA; &ldquo;what is the machine doing right now?&rdquo; Common control modes are: &#xA; &#xA; Idle - the default control mode, machines revert to Idle whenever they&rsquo;re&#xA;not doing anything &#xA; Automation -…

Simple Automation Sequences

Now we can communicate with the outside world, let&rsquo;s start interacting with the&#xA;&ldquo;hardware&rdquo; attached to our motion controller. This will be the beginning of our&#xA; Motion system. &#xA; The simplest way to interact with the world is by executing a pre-defined&#xA;routine, and one of the simplest useful routines is to move all axes to the&#xA;home position. &#xA; &#xA; System…

The Communications System: Part 2

Now we have a mechanism for transferring bytes from the frontend to the&#xA;simulator and back again, we need to translate those bytes into higher-level&#xA;messages. Luckily each [ anpp::Packet ] contains an ID field that&#xA;is designed specifically for this purpose. &#xA; That lets us do something like this: &#xA; // (not real code)&#xA; &#xA; enum Message < 'a > {&#xA; Ping,&#xA;…

The Communications System: Part 1

&#xA; Prelude&#xA; &#xA; &#xA; Link to heading &#xA; &#xA; &#xA; The Communications system is arguably one of the most important parts of&#xA;our simulator. After all, it&rsquo;s kinda hard to debug a program when you can&rsquo;t&#xA;ask it why something isn&rsquo;t working. &#xA; The user will interact with our simulated motion controller via a single&#xA; Serial Port , which we&rsquo;ll be…

FPS Counter

As mentioned in the previous article the next task is to&#xA;implement our first proper System , the FpsCounter . &#xA; &#xA; A relatively easy, yet important, component is some sort of FPS counter.&#xA;Ideally there’ll be a bit of text in the corner showing the number of&#xA; poll() s per second and the average duration. That way we can get a better&#xA;feel for our simulator’s performance…

Top-Level Infrastructure

As mentioned in the intro article , the first task will be to set&#xA;up the application&rsquo;s structure and define how the various components will&#xA;communicate. &#xA; &#xA; Multitasking&#xA; &#xA; &#xA; Link to heading &#xA; &#xA; &#xA; Most embedded systems will implement multi-tasking by rapidly polling each&#xA;system within an infinite loop. &#xA; loop {&#xA; poll_comms();&#xA;…

Announcing Adventures in Motion Control

This is the first installation in my Adventures in Motion Control series. &#xA; At $JOB we build industrial CNC machines, and while developing a simulator&#xA;for our machines I noticed a distinct lack of online resources on how&#xA;they work under the hood. Hopefully this series will address the situation. &#xA; &#xA; The Goal&#xA; &#xA; &#xA; Link to heading &#xA; &#xA; &#xA; The goal for this…

About Me

I&rsquo;m Michael Bryan, a software engineer based in Perth, WA, with a passion for building resilient systems and elegant solutions. &#xA; &#xA; Professional Overview&#xA; &#xA; &#xA; Link to heading &#xA; &#xA; &#xA; I&rsquo;m currently a Senior Software Engineer at Multiversal Ventures , primarily focused on developing robust web crawlers at scale and leveraging ML to extract information from…