Thread overview
Boy, std.bitmanip.bigEndianToNative is annoying to use
May 22, 2015
H. S. Teoh
May 22, 2015
Jonathan M Davis
May 22, 2015
In the spirit of forum bickering, ;-) I stumbled upon this D wart today: I'm reading some data from a file into a ubyte[] buffer, and I want to use bigEndianToNative to convert ushort values in the file data into native byte order (whatever the native order might be).

Sounds simple, right? Unfortunately, bigEndianToNative asks for ubyte[n] as input. Meaning, this doesn't work:

	ubyte[] buf = ... /* allocate buffer here */;
	file.rawRead(buf);	// Read the data

	ushort myValue = bigEndianToNative!ushort(buf[4 .. 8]); // NG

The last line doesn't compile, 'cos you can't convert a slice of ubyte[] into ubyte[4].

I can think of no easy way to declare a temporary ubyte[4] to make bigEndianToNative happy, other than this silly verbosity:

	ubyte[4] tmp;
	tmp[] = buf[4 .. 8];
	ushort myValue = bigEndianToNative!ushort(tmp);

and I have to do this for every single numerical field in the data buffer that I need to convert. :-(  Why should I copy data around that's already sitting in a ubyte[] buffer intended precisely for the purpose of doing such conversions in the first place??

The docs for bigEndianToNative claims that this is to help "prevent accidentally using a swapped value as a regular one". But I say, "Why, oh why???" :-(

This is a very anti-user kind of API. How did we think such a straitjacketed API was a good idea in the first place?!


T

-- 
Curiosity kills the cat. Moral: don't be the cat.
May 22, 2015
On Friday, 22 May 2015 at 19:10:41 UTC, H. S. Teoh wrote:
> In the spirit of forum bickering, ;-) I stumbled upon this D wart today:
> I'm reading some data from a file into a ubyte[] buffer, and I want to
> use bigEndianToNative to convert ushort values in the file data into
> native byte order (whatever the native order might be).
>
> Sounds simple, right? Unfortunately, bigEndianToNative asks for ubyte[n]
> as input. Meaning, this doesn't work:
>
> 	ubyte[] buf = ... /* allocate buffer here */;
> 	file.rawRead(buf);	// Read the data
>
> 	ushort myValue = bigEndianToNative!ushort(buf[4 .. 8]); // NG
>
> The last line doesn't compile, 'cos you can't convert a slice of ubyte[]
> into ubyte[4].
>
> I can think of no easy way to declare a temporary ubyte[4] to make
> bigEndianToNative happy, other than this silly verbosity:
>
> 	ubyte[4] tmp;
> 	tmp[] = buf[4 .. 8];
> 	ushort myValue = bigEndianToNative!ushort(tmp);
>
> and I have to do this for every single numerical field in the data
> buffer that I need to convert. :-(  Why should I copy data around that's
> already sitting in a ubyte[] buffer intended precisely for the purpose
> of doing such conversions in the first place??
>
> The docs for bigEndianToNative claims that this is to help "prevent
> accidentally using a swapped value as a regular one". But I say, "Why,
> oh why???" :-(
>
> This is a very anti-user kind of API. How did we think such a
> straitjacketed API was a good idea in the first place?!

Isn't the problem that you're trying to convert to a ushort, and a ushort is _2_ bytes, not 4? If you sliced it correctly, it would compile. For instance, this code compiles just fine for me with dmd master:

void main()
{
    import std.bitmanip;
    auto buf = new ubyte[](32);
    auto result = bigEndianToNative!ushort(buf[0 .. 2]);
}

But if I change it to buf[0 .. 4], then it fails to compile. So, the fact that bigEndianToNative is taking a static array is actually catching a bug for you.

- Jonathan M Davis
May 22, 2015
On 5/22/15 12:21 PM, Jonathan M Davis wrote:
> But if I change it to buf[0 .. 4], then it fails to compile. So, the
> fact that bigEndianToNative is taking a static array is actually
> catching a bug for you.

Profession of undying love for D language in 3, 2, 1, ... :o) -- Andrei