Thursday, December 2, 2021

RAII guards in Rust

While experimenting with scope rules in Rust, I ended up implementing a recurrent idea I had – a RAII guard that runs a function when the object goes out of scope. I’m well aware of scopeguard crate, but it has some stinky unsafe bits in its implementation.

I was never able to properly implement it, probably because my Rust skills weren’t good enough, but now I did. And I’m rather satisfied with it:

use std::ops::Deref;

/// Returns the object wrapped in a way that the associated closure will run
/// when it goes out of scope.
pub struct Guard<T, D: FnOnce(&mut T)> {
	asset: T,
	dropper: Option<D>,
}

impl<T, D: FnOnce(&mut T)> Drop for Guard<T, D> {
	fn drop(&mut self) {
		self.dropper.take()
			.map(|d| d(&mut self.asset));
	}
}

impl<T, D: FnOnce(&mut T)> Deref for Guard<T, D> {
	type Target = T;

	fn deref(&self) -> &Self::Target {
		&self.asset
	}
}

impl<T, D: FnOnce(&mut T)> Guard<T, D> {
	/// Creates a new `Guard` object.
	pub fn new(asset: T, dropper: D) -> Guard<T, D> {
		Self { asset, dropper: Some(dropper) }
	}
}

I though about writing stuff like this in WinSafe:

impl HWND {
	pub fn GetDC(self) -> WinResult<Guard<HDC, impl FnOnce(&mut HDC)>> {
		Ok(Guard::new(
			self.GetDC()?,
			move |hdc| {
				self.ReleaseDC(*hdc).expect("Guard crash.");
			},
		))
	}
}

But then there are big implications like CreateMenu, which may or may not require a DestroyMenu call. These dubious behaviors are very unsettling, and many questions arise:

  • Should I write another method, with a _guarded suffix?
  • Mark the unguarded original as unsafe?
  • In the example above, self is copied into the closure – what if it’s still zero?

So by now I believe I’ll leave everything as it is, and let the defer-lite crate at hand when needed.

Still, I greatly miss the idiomatic defer in Go.

Thursday, November 25, 2021

Bash script to deploy my own Rust tools

While developing my own personal tools in Rust – which seems to be “the one” language of my own stuff now, after the disappointment of the consistent Go crashes –, I often need to compile and replace the current *.exe tool. The compile line I use is rather long, plus I want to standardize the steps, so I put out a shell script to automate the tasks.

This shell script must be placed at the project root.

EXE=program-name.exe

echo "Compiling $EXE..."
RUSTFLAGS="-C target-feature=+crt-static" cargo build --release --target x86_64-pc-windows-msvc

echo "Replacing old $EXE..."
mv ./target/x86_64-pc-windows-msvc/release/$EXE /d/Stuff/apps/_audio\ tools/.

echo "Cleaning up..."
rm -rf ./target/release
rm -rf ./target/x86_64-pc-windows-msvc

echo "Done."

I’m not versioning this script because it contains the directories on my computer, plus the command line itself is commented in the Cargo.toml file.

Wednesday, November 17, 2021

Fixing Visual Studio Code icon overlay color in Linux

A few months ago I had to dig into Visual Studio Code source until I found a change in the built-in light theme, where they changed the overlay color of the suspended autocomplete menu. This ended up being a question and an answer on StackOverflow, and it made up to my Windows patch.

There’s no patch for Linux, though. Another jab at my lack of multiplatform GUI framework – but I digress.

So, for the record, with Visual Studio Code standard *.deb installation, this is the file with the light theme:

/usr/share/code/resources/app/extensions/theme-defaults/themes/light_vs.json

The line to be commented out is:

"list.activeSelectionIconForeground": "#FFF"

Tuesday, November 9, 2021

Stateful iterators in Go

I’m writing an insane amount of Go code lately. It’s really unobtrusive, allowing you focus on the problem you have to solve. And I’ve been dabbling with iterators in Go for a while, since I started to used them in Rust – which is so much better than C++ in this regard.

Today, when researching the topic again, I found a very nice article on the matter, exploring a few possibilities. The most performant approach is a stateful iterator, which can be implemented as:

type IterFive struct {
	count int
}

func NewIterFive() IterFive {
	return Iter{}
}

func (it *IterFive) Value() int {
	it.count++
	return it.count - 1
}

func (it *IterFive) Ok() bool {
	return it.count < 5
}

func main() {
	for iter := NewIterFive(); iter.Ok(); {
		println(iter.Value())
	}
}

I’m still unsure whether I should adopt interators instead of simply allocating and returning slices for some functions, but I’m considering it. The main reason would be performance, but it could be qualified as premature in the cases I’m dealing with in Windigo.

Friday, November 5, 2021

Static linking of the C runtime in Rust

By default, Rust on Windows with MSVC toolchain compiles to a dynamically linked C runtime, apparently following the default configuration on Visual Studio, which uses the /MD compiler flag. In order to use static linking for the C runtime, we must change this to /MT, something I’m used to do in my C++ Visual Studio projects.

I found notes about Rust linkage, which hints us specifically about these /MD and /MT switches, although not citing them explicitly. The way to specify static linking is through RUSTFLAGS environment variable:

RUSTFLAGS='-C target-feature=+crt-static' cargo build --release --target x86_64-pc-windows-msvc

Which is rather ugly, let me say. At least it appears to work, and this is the command line I’m using for my release builds now.

Friday, October 22, 2021

Displaying custom fields in foobar2000

Today I found the TOPE frame in the ID3v2 tag specification, which can be used in cover songs. I was simply using the comment frame so far, and having a specific frame for that is great. Now I needed to display this frame in foobar2000, my player of choice for years.

I created an account in foobar2000 forums and posted the question there. Then I just found a specific subreddit, and I posted the same question.

Much to my amusement, I got answers in both after a few minutes.

Turns out, I vaguely remember having done this before. One must navigate to Preferences > Advanced > Display > Properties dialog > Standard fields, and add:

Original Artist=ORIGINAL ARTIST;

And it worked.

Tuesday, September 28, 2021

Enhancing Chrome 94 privacy

Unfortunately Firefox is getting worse every day, specially after the introduction of the horrible v89 interface. Having to resort to Chrome again demands some precautions.

Latest Chrome 94 introduced an idle detection feature, which is a privacy nightmare. Fortunately, we still can disable it here:

chrome://settings/content/idleDetection

And don’t forget to also disable the privacy sandbox and FLoC features:

chrome://settings/privacySandbox

I really wish I could go back to ol’ good Firefox.