Skip to content
DevMeme
3352 of 7435
Rust bitwise function: Comment says reading hurts, writing it was even worse
CodeQuality Post #3683, on Sep 12, 2021 in TG

Rust bitwise function: Comment says reading hurts, writing it was even worse

Why is this CodeQuality meme funny?

Level 1: Puzzle Pieces

Imagine you have a secret message that’s been cut into tiny pieces and hidden in a few different places. Reading the message means you first have to find all those little pieces and put them together in the right order – pretty hard to do! Now think about the person who originally took the message and cut it up into that crazy puzzle. Figuring out how to chop it into bits and scatter them must have been even more challenging than simply solving the puzzle. That’s exactly the joke here: the code is like a secret message split into bits, and even though it’s hard to understand (like a tough puzzle), the person who wrote it had an even tougher job creating it in the first place. It’s funny because the writer is basically saying, “If you think solving this is painful, just imagine how painful it was for me to make it!”

Level 2: Bits and Pieces

Let’s step back and explain what’s going on in that scary Rust code. We have a function fn load_maj_min(block: [u8; 4 * 15]) -> (u16, u32) – that means it takes an array of bytes (u8 means an 8-bit unsigned integer, so 0 to 255) of length 60 (since 4 * 15 = 60). It returns a tuple of two numbers: a u16 (16-bit unsigned, 0 to 65535) and a u32 (32-bit unsigned, a much larger range). These likely correspond to some two-part identifier (the name hints at “major” and “minor” parts of something, like version numbers or device IDs).

Inside the function, there’s an if condition: if 0 != block[0] || 0 != block[1]. In plain terms, “if either block[0] or block[1] is not zero…”. If that condition is true, it returns (block[1] as u16, block[0] as u32). This suggests a simple case where maybe the first two bytes directly give the two values (with block[1] used for the smaller u16 and block[0] for the larger u32). The use of as u16 and as u32 is Rust’s way to convert the 8-bit value into a 16-bit or 32-bit type so it can be returned (and possibly combined with other bits). If the condition is false (meaning both block[0] and block[1] are zero), the code goes into the else branch – and that’s where the wild bit-manipulation happens.

In that else, the author left a sarcastic comment in red: “if you think reading this is bad, I had to write it.” It’s a little heads-up that the code below is complicated. And indeed, below it we see a gnarly one-liner expression that constructs the two return values by combining various block[X] entries with bit operations. To understand it, let’s break it into pieces and use simpler terms:

  • Bit masks: You see things like 0b0000_1111 and 0b1111_0000. In binary, 0b0000_1111 equals 15 in decimal, which in binary has the lower four bits as 1s (0000 1111). Using a mask like this with a bitwise AND (&) lets you keep just those lower 4 bits of a byte and discard the upper 4. Conversely, 0b1111_0000 (240 in decimal) has the upper four bits as 1s (1111 0000), so value & 0b1111_0000 would keep only the top 4 bits of value and zero out the rest. This is how you isolate nibbles (4-bit chunks) from a byte.

  • Shifting: The << 8 or >> 4 operations shift bits left or right. Shifting left by 8 bits (<< 8) is like multiplying by 256, which effectively moves a byte’s worth of bits to higher positions (making room for lower bits to be filled by something else). Shifting right by 4 (>> 4) moves bits to lower positions, dropping some off. These are used to align pieces of data before joining them together.

Now, the code basically does:

  1. For the u16 value (let’s call it major): take block[5] and some bits from block[6].
  2. For the u32 value (minor): take block[4], block[7], and some bits from block[6].

It might be easier to read in a more expanded form. Here’s an equivalent breakdown of what the else is doing in a step-by-step way:

// Assuming block is our [u8; 60] array:

// Extract the 12-bit "major" number from block[5] and block[6]:
let major_low8  = block[5] as u16;                // lower 8 bits come from byte 5
let major_high4 = (block[6] & 0x0F) as u16;       // lower 4 bits of byte 6 (0x0F = 0000_1111)
let major      = major_low8 | (major_high4 << 8); // combine to form a 12-bit value

// Extract the 20-bit "minor" number from block[4], block[6], and block[7]:
let minor_low8  = block[4] as u32;                // bits 0-7 come from byte 4
let minor_mid4  = ((block[6] & 0xF0) as u32) >> 4; // upper 4 bits of byte 6 (0xF0 = 1111_0000), shifted down to bottom
let minor_high8 = (block[7] as u32) << 12;        // bits 12-19 come from byte 7 (shifted up 12 bits)
let minor       = minor_low8 | (minor_mid4 << 8) | minor_high8; // combine all parts

// Now `major` and `minor` hold the reconstructed values.

Each of those steps uses basic operations:

  • block[5] as u16 takes the 8-bit value and prepares it as part of a 16-bit number.
  • (block[6] & 0x0F) gets the lower 4 bits of block[6]. Shifting that left 8 bits (<< 8) moves those 4 bits into the upper 4 bits of a 12-bit region (because 4 bits shifted by 8 positions becomes bits 8-11 in a number).
  • OR-ing (|) the parts together assembles the final number by setting the bits from each part.

The result: major is a 12-bit number composed of byte5 and half of byte6; minor is a 20-bit number composed of byte4, the other half of byte6, and byte7. This is like taking pieces of a puzzle (some bits from here, some from there) and fitting them into a larger number.

For a junior developer, the key takeaway is understanding those bit operations:

  • AND with a mask (& mask): picks specific bits out of a value (mask has 1s in the positions you want to keep).
  • OR (|): combines bits from two values (if a bit is 1 in either input, it becomes 1 in the result, which is great for assembling non-overlapping parts).
  • Shift left/right (<<, >>): moves bits over, which is how you line up pieces to the correct place value.

In practice, you’d encounter code like this whenever dealing with data formats or protocols that pack multiple values into a smaller space. For example, reading a color value from a pixel where it packs R, G, B into one integer, or decoding flags in a network packet header. You learn to read it by mentally mapping what each part is doing. But until you get used to it, it’s pretty tough to follow – which is exactly why the comment in the code is poking fun at the situation.

And that comment itself? It’s a light-hearted way for the coder to say “Yeah, sorry about the complexity… but believe me, implementing it was no picnic either.” It’s a nod to the next developer (or their future self) that “I know this looks crazy. I’m with you. It hurt to write, so I empathize if it hurts to read.” In terms of CodeQuality, it’s usually better to make code clear and maintainable. But sometimes, especially in LowLevelProgramming, the problem itself is complex, and even well-written code will look a bit like hieroglyphics. At least a witty comment can bring a smile and a bit of shared camaraderie among developers who deal with such CodeComplexity. After all, this is DeveloperHumor: turning a frustrating piece of code into a moment of connection (and a meme) by acknowledging the pain with a chuckle.

Level 3: Masked and Confused

This meme hits home for any developer who’s had to muck around with low-level bit manipulation. The code shown is a Rust function that’s doing byte swapping and combining, and it comes with a painfully relatable comment:

// if you think reading this is bad, I had to write it

In other words, the author knows their code is practically indecipherable at first glance, and they’re preemptively commiserating with us. The humor lands because we’ve all been there: sometimes you have to write code that is correct and efficient but utterly opaque. In this case, it’s slicing and dicing bits from a byte array to form two numbers. It’s the kind of code where you double-check every mask and shift, then add a comment because you know the poor soul maintaining it (which might even be future you) will be confused and possibly horrified.

Let’s break down why this snippet is so gnarly. First, it’s Rust, a language celebrated for high-level safety, but here we’re as low-level as it gets. We’re dealing with raw u8 bytes and manually constructing a u16 and a u32. Rust’s strict typing forces a lot of explicit casts (as u16, as u32) to combine different integer sizes. While that’s good for clarity about types, it adds to the visual clutter. Then we have binary literals like 0b0000_1111 which is a neat way to write 0x0F (the mask for the low 4 bits) – Rust lets you use underscores to separate bits, which is a small mercy for readability. But even with that, the logic is a dense chain of bitwise ANDs &, ORs |, left shifts <<, and right shifts >>. This is classic bit-fiddling: taking bits from here and shoving them over there. The code is effectively saying, “Take byte 5 as the lower part of the 16-bit number, then take 4 bits from byte 6 as the upper part.” And similarly, it assembles the 32-bit number from bytes 4, 6, and 7, each contributing different portions.

Why would anyone write such a thing? Typically because the data is coming from some external source (maybe a binary file or a hardware register) that packs values tightly. Instead of storing a 16-bit and 32-bit number separately in a straightforward way, some clever (or cruel) format designer decided to save space by packing them into a few bytes with overlapping bits. This saves a few bytes on disk or wire, but it means every implementation must include this little decoding dance. A senior developer recognizes this pattern immediately – it screams "bitfield parsing" or "packed struct". It’s the kind of code you find in systems programming, embedded device firmware, or high-performance code where you can’t afford extra bytes.

The comment itself is a gem of developer humor. It’s simultaneously apologizing and bragging. Apologizing for the reader’s impending headache, and bragging (tongue-in-cheek) that the author went through an even worse ordeal to make it work. There’s a shared understanding here: reading someone else’s bit-twiddling code is hard, but actually inventing and writing that code correctly requires a special kind of patience (and masochism). This kind of sarcastic comment in code is a coping mechanism – a way to say “Yeah, I know this code is ugly. Trust me, I suffered to get it right.” Seasoned devs might chuckle because they’ve written something just as bad or reviewed code that made them go cross-eyed, and sometimes the only thing you can do is leave a snarky comment or two.

From a code quality standpoint, this snippet is a trade-off between efficiency and readability. It probably works fine and might even be optimal, but it’s not obvious at a glance what it does. A code reviewer might suggest, “Can we add some helper functions or at least more comments to explain these magic numbers?” A common practice is to break down such expressions or use constant names (e.g., LOWER_NIBBLE_MASK = 0x0F) to indicate intent. But when you’re in the zone writing this, you might just get it working and think, “I’ll document it later… or at least warn people with a comment.” LowLevelProgramming often puts us in this bind: we want clean CodeReadability, but the logic itself is inherently complex. And in languages like Rust (or C/C++), you sometimes have to get your hands dirty with bit math; there’s no abstraction to save you.

Ultimately, the humor here is “it hurts, I know.” It’s funny because it’s true – both reading and writing such code is a brain strain. The comment is universally relatable to developers as a wink and a nod: this code is ugly, but necessary – sorry (not sorry). The meme exposes that shared pain with a laugh. After all, part of being a programmer, especially a systems programmer, is occasionally writing code that looks more like encrypted binary and less like English, then bonding with your peers over how awful it is to deal with. Masked and confused, indeed.

Level 4: Major Minor Mayhem

At the deepest technical level, this snippet is wrestling with binary data encoding and the legacy of how operating systems pack information into bits. The function load_maj_min appears to reconstruct a major and minor number pair (hence the name) from a raw byte array. This hints at something like device IDs in Unix/Linux systems, where historically a device number was split into a major part (identifying the driver type) and a minor part (identifying a specific device). Over time, as systems grew, the size of these numbers had to expand, leading to tricky bit-packing schemes for backward compatibility. Here we see the code detecting which scheme to use: an if checks if the first two bytes are non-zero (perhaps an indicator of an older format) and otherwise falls back to an “extended” encoding using additional bytes.

Why all the bit gymnastics? It’s about packing more information into fixed-size fields without breaking old assumptions. In older Unix, a device number was just 16 bits (8-bit major + 8-bit minor), limiting the number of devices. Modern systems use 32 bits total (e.g. 12-bit major and 20-bit minor), which is what this code assembles. Those weird constants 0b0000_1111 and 0b1111_0000 are bit masks to isolate 4-bit nibbles. The code is effectively doing what a kernel macro might do in C: splitting and combining bit fields to extract the original values. Each shift (<< or >>) moves bits into position, each mask (&) cherry-picks specific bits. This is bitwise arithmetic at play: fundamentally simple operations that, in combination, become a dizzying puzzle.

From a computer architecture perspective, this is leveraging how data is laid out in memory. The code assumes a particular endianness (likely little-endian, given how it assembles the values with lower-order bytes first). On little-endian systems, the least significant byte of a number comes first in memory. Notice how block[4] (a later index) ends up as the least significant bits of the 32-bit number, suggesting the data was stored little-endian. In a lower-level view, the CPU doesn’t care about “major” or “minor” — it just sees bits. It’s the program’s job to mask and shift those bits into the right places. This kind of manual bit-fiddling is often needed in systems programming, and languages like Rust (being a systems language) give you the tools to do it safely (with checks) but not always prettily.

On a theoretical note, bit manipulation exploits properties of binary math. Shifting left by 8 (<< 8) is equivalent to multiplying by $2^8 = 256$, and masking with 0b0000_1111 is like taking a number mod 16 to get the lower 4 bits. It’s elegant in theory — you’re effectively working in base-2 arithmetic — but in practice, aligning multiple fields into a non-standard size (like 12 and 20 bits) feels like solving a Rubik’s cube made of 1s and 0s. The humor in the comment (“reading this is bad, writing it was worse”) is richly deserved: the writer had to ensure every single shift and mask is correct so that the bits fall into place like bitfield Tetris. One wrong shift and the major and minor numbers would come out garbage. This level of precision is both the beauty and pain of low-level programming. Seasoned developers have fought these bit battles before; they know that this mayhem of bits comes from years of layering new requirements onto old data formats. It’s a war story told in binary, and every 0b1111_0000 in that code is a scar from a past design decision that won’t die easily.

Description

Screenshot of a light-themed code editor showing a Rust function definition: "fn load_maj_min(block: [u8; 4 * 15]) -> (u16, u32) {". The if-branch simply swaps bytes when block[0] or block[1] is non-zero. The else-branch contains a single-line comment in red highlight: "// if you think reading this is bad, I had to write it". Below, several tightly packed expressions combine block[5]-block[7] with masks "0b0000_1111" and "0b1111_0000" and multiple left/right shifts to construct u16 and u32 values. The snippet showcases painful bit-fiddling, byte ordering, and mask-and-shift logic that sacrifices readability, a common low-level programming headache that seasoned developers will recognize and laugh at

Comments

16
Anonymous ★ Top Pick Bit-twiddling in Rust is when I start missing C - at least in C the undefined behavior is upfront, not buried under four masks, two endiannesses, and a comment from past-me apologizing in advance
  1. Anonymous ★ Top Pick

    Bit-twiddling in Rust is when I start missing C - at least in C the undefined behavior is upfront, not buried under four masks, two endiannesses, and a comment from past-me apologizing in advance

  2. Anonymous

    This is what happens when you need to parse a binary format that was clearly designed by someone who measured memory in punch cards and thought endianness was a personality trait - now you're writing Rust that looks like you're defusing a bomb made of pointers while blindfolded

  3. Anonymous

    This is the code equivalent of 'I'm sorry you had to see that' - when your bit-twiddling logic becomes so gnarly that you preemptively apologize to future maintainers. The real tragedy? This is probably the *cleanest* way to parse major/minor device numbers from a byte array without pulling in a dependency. Welcome to systems programming, where the comments are apologies and the bit shifts are nested deeper than your call stack during a production incident

  4. Anonymous

    Semver packed across nibbles with endian roulette - Rust guarantees memory safety, not spec sanity

  5. Anonymous

    Optimizations so tight, they escaped the event horizon of readability - good luck grepping for bugs

  6. Anonymous

    Saving two bytes in the wire format costs three casts, four shifts, and a headcount for maintenance

  7. @LonelyGayTiger 4y

    What the actual fuck

  8. @Kryvashek 4y

    Look like some crypto calculations. Doesn't look terrible, looks usual.

  9. @VolodymyrMeInyk 4y

    sad but true

  10. @LionElJonson 4y

    Actual comment would be more useful

  11. @dmytro_sukhariev 4y

    Is it Rust Lisp?

    1. @sylfn 4y

      https://t.me/dev_meme/3667 > Please use English in this chat. Fast translation (may be inaccurate): Is it Rust Lisp?

  12. @cfyzium 4y

    if 0 != block[0] || 0 != block[1] { These Yoda conditions are the most disturbing part of the snippet. Rust does not even compile misprints like block[0] = 0 =___=.

    1. @sylfn 4y

      misprints like block[0] = 0 sometimes are not misprints

      1. @Agent1378 4y

        Yes, these are flaws of the language itself.

  13. @cfyzium 4y

    Still, neither Rust nor C++ with -Werror will let you make an unintentional mistake there (inside a condition expression).

Use J and K for navigation