Hacker News new | ask | show | jobs
by Laremere 634 days ago
This is a reasonable way to do things, and I've used it before. However I just used Zig's method here, and like it a lot: https://ziglang.org/documentation/master/std/#std.io.Reader....

Given a reader (file, network, buffers can all be turned into readers), you can call readInt. It takes the type you want, and the endianess of the encoding. It's easy to write, self documents, and it's highly efficient.

1 comments

If we're talking about a single int, the way you do it doesn't matter, just wrap it up in a readInt function.

But if we're talking about a struct or an array, if you're byte-order aware you can do things like memcpy the whole thing around that you couldn't do by assembling it out of individual readInt calls.

It's probably faster to memcpy the thing then "swap" each element (the swaps may be no-ops under the hood). This should be portable and fast.
Yeah it's not a hard thing to do, but I think Zig does it very cleanly.

As for reading structs, that's supported too: https://ziglang.org/documentation/master/std/#std.io.Reader....

readStructEndian will read the struct into memory, and perform the relevant byte swaps if the machine's endianness doesn't match the data format. No need to manually specify how a struct is supposed to perform the byte swap, that's all handled automatically (and efficiently) by comptime.

Comptime also means that when endianness matches, using these functions is a no-op. I expect you know this, but those new to the language may not: the endianness check in the implementation happens when compiling, not when decoding structs.

It's instructive how different in feel this solution is to the traditional #ifdefs which the Fine Article dislikes enough to write an entire (IMHO very confused and opaque) broadside against. The preprocessor is a second language superimposed over the first, which is friction, and the author would rather trust the compiler (despite explicitly noting that MSVC cannot be so trusted!) to optimize out a non-obvious solution using shifts, rather than risk the bugs which come with preprocessor-driven conditional compilation.

By contrast, if you don't know Zig, it's not all that obvious that the little-to-little case is a no-op on little-endian systems. If you do know Zig it is obvious, and it's also boring, in a good way: idiomatic Zig code does a lot of small things at compile time, using, for the most part, the same language as runtime code.