This app does not collect, use, store, or share any personal or sensitive user data.
This app does not collect, use, store, or share any personal or sensitive user data.
I’m a Finnish undergraduate CS student at Aalto University.
I am very interested in software architecture, performance optimizations and designing scalable, reliable software.
There are a lot of open-source projects on my Github, including reload, a Go middleware package and arctis-battery-indicator, a Windows task bar program written in Rust.
📮 Contact me #Github: https://github.com/aarol
Telegram: @aaroluo
Discord: @aarol
Email:
PGP Public key | Fingerprint: 3DCE 9204 79EF 33DD A093 6BEC 430F BBCD 792C C9E6
Everyone knows the classic print("Hello World") program they might have written when they first started learning programming. Recently, I saw a meme version of it, where instead of print("Hello World"), it’s HelloWorld("print") accompanied by Elliot from Mr.Robot saying “Sometimes I dream of saving the world”.
It’s incredibly stupid, but it made me think if it was actually possible to define a function like that.
Recently, I’ve gotten hooked on the game Elite Dangerous, a space flight simulation game which contains a 1:1 scale replica of the Milky Way galaxy. In the game, players can use ships to jump between star systems, with a very limited range (usually around 80 lightyears).
There are around 400 million stars discovered by players. A small fraction, around 4.4 million of them, are especially important for explorers. They are a specific type of star, the neutron star1. I’ve been working on a web app which (among other things) visualizes neutron stars in a galaxy view.
I have an open source project which uses GitHub Releases as its binary distribution platform. I have a GitHub actions workflow which builds the Rust project using cargo, creates an installer and creates something called a “build provenance attestation”, which is a verifiable signature of the installer binary, created and managed by GitHub using SigStore. This can paired with a wordy GitHub CLI command such as gh attestation verify HeadsetBatteryIndicatorSetup.exe -o aarol on the downloaded binary to verify that the file on the releases page was actually created in the Actions workflow. This was, for a long time, the only way to verify that a binary was actually authentic.
I’ve recently been working on an app which uses Expo, a framework for React Native. It actually has a pretty nice developer experience, abstracting away many of the ugly parts of app development.
For the project, I needed to rely heavily on native APIs, like the Nearby Connections API, and found out that the best way was to create an Expo module with npx create-expo-module, which creates a Kotlin module where I can define functions and events to send to the application.
I’ve been learning a lot about low-level programming languages lately, and for a long time there has been one thing that has interested me: SIMD (or ‘single instruction, multiple data’) code. I’ve seen a lot of articles about having massive performance gains by utilizing SIMD and wanted to learn how to do it myself.
This article is a journey into implementing ~60% faster substring searching compared to Zig’s std.mem.indexOf using a SIMD-friendly algorithm.
A small icon on the task bar, which displays the battery level of connected SteelSeries Arctis headphones.
I wanted to reduce the number of dependencies in my Rust project, and I noticed that the rust-i18n crate has a lot of dependencies (a whopping 46 of them). Since I didn’t really have that many translations and they didn’t need any special logic, I figured that I could just write a very simple localization function myself.
First, I made an enum in a new file lang.rs to represent all supported languages (just two of them in my case):
I recently saw a bunch of videos about simple particle simulations where there are thousands of tiny 2D balls interacting with each other, and it looked very fun! I wanted to do something very similar, but I also wanted to use Zig, a language that I haven’t used much before but is currently one of the trendiest languages around. This post is primarily about using the Zig build system to build a program that uses SFML to make cross-platform graphics. SFML is a C++ multimedia library (which means that it has more features than just graphics, like networking and audio).
It’s the time of year to start sending some summer job applications again. And is there a better way to procrastinate improve the job searching experience than to generate the CV from simple markup with Typst?
Typst is new1 a typesetting system similar to LaTeX, but has much nicer syntax, and also it’s written in Rust!🤷
In this post I’ll show some basic features of Typst to build a simple CV file that looks like this.
Anyone who has implemented a simple HTTP 1.1 server can tell you that it is a really simple protocol. Basically, it’s a text file that has some specific rules to make parsing it easier.
All HTTP requests look something like this: 1
GET /path HTTP/1.1\r\n
Host: aarol.dev\r\n
Accept-Language: en,fi-FI\r\n
Accept-Encoding: gzip, deflate\r\n
\r\n
The first line is the “request line”, and it has the requested method, path and HTTP version. The following lines are headers, each terminated with “carriage return” and “line feed” characters. There is also an extra CRLF at the end, to mark the end of the header section. After that, there is the message body which can whatever data you want to send.
Making changes to websites is tricky, because even small changes may lead to visual regressions in the page layout. For example, changing a bit of CSS to fix something somewhere may blow up in a completely different place. I could just click around and make sure everything looks okay, but that is boring and error-prone. What if I told you that there is a way to make sure that every pixel on your site is perfect, staying just they way you intended it to be?
Recently, the cushions of my old headset, the HyperX Cloud Stinger, were breaking apart pretty bad. I had been using them for 5+ years at that point, so it was time for an upgrade. I bought a new wireless gaming headset, the SteelSeries Arctis Nova 7. So far, it has been great. I was expecting to feel a noticeable delay in the audio since they are wireless, but I am happy to report that with the 2.4 Ghz wireless adapter there is practically no delay! They have about 38 hours of battery life too. One small issue is that the only way to see how much battery life is left is to look at the color of the LED on the headset, or use the SteelSeries GG application, which has a small battery percentage indicator in the “Engine” tab.
Go package for soft-reloading web server assets
Advent of Code is an annual set of Christmas-themed computer programming challenges that follow an Advent calendar. It has been running since 2015.
The programming puzzles cover a variety of skill sets and skill levels and can be solved using any programming language. Participants also compete based on speed on both global and private leaderboards.
What makes AOC particularly fun is the daily challenge aspect, and the community.
When doing this year’s AOC challenges in Go, I found myself writing a lot of boilerplate code that could be abstracted away. I also found many very useful but unknown functions in the Go standard library. Here’s what I have found:
Dev Drive is a new type of storage volume in Windows 11 that is specially made for programming workloads. Instead of the typical NTFS filesystem, it uses ReFS (Resilient File System), which is a newer filesystem based on Copy-on-Write (COW) linking. Basically, if you have two copies of a file, only one copy actually exists on the disk. The other one exists only as a link to the first one. Then, when you actually write to the linked file, the original data is lazily copied into it (hence Copy-on-Write). This results in much faster writes for duplicate files (or data).
Have you ever shared a link somewhere and wondered where those little preview images of websites come from? Well if you didn’t know, they are called OpenGraph tags. Open Graph protocol was invented by Facebook and is now used by many other social media sites, like X (Twitter), LinkedIn, Reddit, Discord, Mastodon and many others.
They look like this:
<head>
<meta property="og:title" content="Generating OpenGraph images with Hugo" />
<meta name="description" content="Have you ever shared a link somewhere and …">
<meta property="og:image" content="https://aarol.dev/posts/hugo-og-image/og.png">
</head>
There are a bunch more tags, but these 3 are probably the most important ones. Title and description can be easily generated with Hugo, but what about images? There are a bunch of cloud services that offer og:image generation, like Cloudinary or Vercel’s og, but I didn’t want to pay for those. I want my whole website to be static and cheap to host. I managed to generate some sweet og:images using Hugo’s image manipulation tools.
Valmistuin ylioppilaaksi keväällä 2023. Kirjoitin viisi eri ainetta, joista sain seuraavat arvosanat:
Aine Pistemäärä / Max Arvosana L:n pisteraja Äidinkieli 80 / 120 E 89 Pitkä englanti 271 / 299 L 267 Pitkä matematiikka 105 / 120 L 81 Fysiikka 84 / 120 L 81 Kemia 111 / 120 L 99Olin yllättynyt lopullisista arvosanoista, koska preliminäärikokeeni eivät olleet menneet yhtä hyvin. Opettajien arviot pitivät yleensä paikkaansa, mutta fysiikan arvosana romahti opettajan antamasta arviosta 15 pistettä.
After Lastpass suffered a massive data breach last year, I began looking for an alternative password manager. Bitwarden is another centralized password manager like LastPass, but with the added benefit of being completely open source! They also allow you to spin up your own Bitwarden server and connect to them with all of their clients.
Fly.io has a generous free tier, allowing up to 3 virtual machines with 256 MB of RAM, and 3 GB of persistent volume. 256 MB of ram isn’t a lot, but it should be enough, right? As it turns out, Bitwarden’s official server requires a minimum of 2 GIGABYTES of RAM. That is way more than we can afford. This is where Vaultwarden comes in. It’s an unofficial server for Bitwarden, which is written in Rust, runs in a single process with minimal RAM usage, and uses SQLite as the database. They even have a simple Docker image, which we will be using to spin up the server on fly.io.
Compared to Javascript, Python and other single threaded languages, Go takes a very different approach to
I was having difficulties understanding how concurrent Go programs are supposed to work. Coming from single-threaded event-driven languages like Dart and Javascript, it was not easy wrapping my head around things like mutexes or channels. I recently found the Little Book of Semaphores, which is a free ebook that teaches methods for synchronization in concurrent programs. It does this with a primitive called a “semaphore”. I highly recommend reading chapters 2 and 3 of the book to understand semaphores.
http.ListenAndServe(":8080", nil) // bad
http.ListenAndServe("localhost:8080", nil) // good
If you are using Go with Windows, you might encounter a small annoyance when running a http server. When using go run to run the server, Windows Defender will sometimes prompt you for firewall access. Here is an example of a Gin server doing it:
package main
import (
"github.com/gin-gonic/gin"
)
func main() {
r := gin.Default()
r.GET("/ping", func(c *gin.Context) {
c.JSON(200, gin.H{
"message": "pong",
})
})
r.Run() // listen and serve on :8080
}
As you can see, we run the server with (*gin.Engine).Run(addr ...string), but aren’t specifying an address. (*gin.Engine).Run() will call http.ListenAndServe with the default address of “:8080”. The default address only contains the port, not the IP address. Because of this Go’s address resolver will default to using the IP “0.0.0.0”, which is just the host’s network IP address. This means that other devices on the network can connect to it.
You’ll notice that many of these shortcuts are multi-cursor-related. It’s a feature you will miss in every text editor once you get good with it.
Self host variable fonts from Google Fonts
Prerequisites #ATTENTION: there are now several forks of SD that offer web GUI’s and can install on Windows in one click (most notably sd-webgui). If you want to run Stable Diffusion programmatically and don’t mind some extra steps, read on.
In order to run Stable Diffusion locally on Windows, you will need a Nvidia GPU with at least 8 GB of VRAM and the latest Game Ready drivers. We will use WSL2 (Windows subsystem for Linux) to run Stable Diffusion.
Fly.io is a cloud service that can be used to easily deploy fullstack applications on the web. You only pay for what you use, and servers can be scaled up and down easily. Fly.io supports lots of frameworks and Docker images, which will come in handy. I’ll show how you can deploy a Caddy web server serving a single page application with a Go backend.
Getting started #First, you will need to install flyctl and create a fly.io account. Once you have logged in with flyctl, create a new application:
These are the biggest roadblocks for me in adopting linux. I have tried mostly KDE and Gnome, but these issues are common to most DE’s.
While reading the code of flutter apps, I’ve seen this particular piece of code repeated way too many times:
return MaterialApp(
theme: ThemeData.dark().copyWith(
textTheme: ...
),
home: ...
)
This is problematic for a couple reasons that become clear when we take a peek at how ThemeData works.
This is taken directly from the material library’s code:
factory ThemeData.dark() => ThemeData(brightness: Brightness.dark);
That is all that it does. It just changes the brightness parameter from light to dark. What does the source code for copyWith look like? Well, you can take a look for yourself.
There are a lot of units to remember in physics. I often make errors because I forget to multiply by something, or I’m mixing up meters and kilometers by mistake. Wouldn’t it be convenient to not have to worry about that and make the computer to it instead? I recently found out that SpeedCrunch, which is a fast & minimal open-source scientific calculator, happens to support units really well.
Say we have a velocity and time, and we want to find the displacement s where
$$
s=v*t
$$
The app I’m currently building has a feature which displays a custom wallpaper on the home screen. It involves the user choosing an image from their gallery and cropping it to their device’s aspect ratio. The app then modifies the image and sets it as the background.
There’s just problem: How do I get the pixel dimensions of the screen?
Screen height in Flutter #After a bit of searching, I found this property in the dart:ui package:
This is the first post on my website. I made this website to host anything that I want to publish. My number one goal is to write about things that atleast one person somewhere might find useful. Solutions to problems that I have encountered, guides on languages/frameworks or just something cool I want to share.
Static site generation #Static site generators output plain html/css/js, ready to be served anywhere. When designing this site I had to decide which framework to use. NextJS and Gatsby both provide static site generation and I already know React and Javascript so I naturally went for them first. They are the most popular static site generators, so why not use them?
A small utility to delete folders easily