Rust Diaries

KTHXBAI

As I wrote before, time is precious. I’m not going to invest my time into what’s not even a steep learning curve but a vertical bloody wall that disappears into the clouds. Thanks but no thanks.

TLDR: RAD – MAD – SAD

Time is precious.

RAD

MAD

SAD

In Case You’ve Too Much Time On Your Hands

Story time!

The Custom Build Script

After a few hours of getting going I already had to wrap the cargo tool with a script of my own making. Why, I hear you ask.

Because of a STFU WONTFIX. That, alas, is seldom a trait of maintainers that listen and care. Also, let me not get started of the utter inconsistencies that’s the output (both content and format) of the build toolchain.

Cargo, when running in test mode, i.e. when building and running tests, will make the compiler report errors in production code twice(!), as it’s also building for some ‘documentation test’ mode that may turn out to be valuable later but I definitely don’t care about for the time being. And in any case, running the standard build tool with a standard target MUST NOT produce duplicate error reports or else IT’S A BUG. Of course the maintainers disagree and have all sorts of internal reasons to cite, ignoring user needs, labelling , gazing navels as they do.

My solution is a wrapper script in three stages, first building the production code to pick up bugs from src, then building the tests to pick up bugs from tests, and only then running said tests, thereby keeping errors handling separate from the mess that’s the test output. Because another reason behind the script is to clear up the noisy and inconsistent reporting of source locations and diagnostic messages, so that the editor can have a chance of integrating. Test output is also aggregated by the script, as integration tests are segregated per individual files in the tests folder, producing a long-winding and almost unreadable data dump. This cargot (as in cargo test) script can be found in the bin folder of the repository.

Note, the accompanying Sublime build file is in my tidbits repository.

The Custom Assertions

After a day or so of getting going, I already had to wrap all assertions and opt for using mine only. Why, I hear you ask.

Because of inconsistency. That, alas, is seldom a trait of clear thinkers.

This is how assert_eq!(1, 2) reports the failure:

thread 'assert_equal' panicked at 'assertion failed: `(left == right)`
  left: `1`,
 right: `2`', tests/qsh_test.rs:30:5

And this is how assert!(1 == 2) reports the failure (redacted to fit):

thread ... panicked at 'assertion failed: 1 == 2', tests/qsh_test.rs:25:5

Yeah. Try to feed that output into your editor. Also, note how there’s no concept of expected vs actual in assert_eq!(left, right).

Instead of wrangling with the output in the cargot script I chose to implement my own matchers, you find these in the tests/helper/mod.rs file. Fortunately the macro system appears to be quite capable so implementing an own matcher was no big deal, my only problem is that the invocation is a tad bit noisy with that extra semicolon in should!(actual; be expected). The overloading capability of macros that allows adding other matchers like should!(actual; contain expected) is outright powerful, reminds me of Haskell and Elixir. RAD! Aesthetics are less than perfect though, as usual. I even moved away from it, see The Ugly Bits below.

The Ugly Bits

What do you mean by ‘aesthetics’, beauty is in the eye of the beholder, I hear you say. Actually, not quite. Personal preferences aside there are things that violate the integrity and harmonies of a facade. A sampler.

Macro Overloading

So in this expression should!(2 * 2; be 2 + 2) the argument separators are… semicolon(!) and blank(!!!). On which planet do we use ANY of those (when not in freaky DSLs)??? This was so ugly, it made me abandon the otherwise powerful macro overloading.

Lifetime Annotation

So if you thought that single quotes are to be used for encapsulating charactery things then you’re wrong because Rust decided to use them as apostrophes, thereby making brainfucks like struct Bar<'a> {foo: &'a (dyn Foo + 'a)} valid. If anything, they should’ve used backticks, though I seriously doubt there had not been a better way.

Feedback Et Al

Anyways, hope it all made sense. In case you’d have anything to share, you find me here. Cheers!