www.digitalmars.com         C & C++   DMDScript  

digitalmars.D.learn - bitmanip bigEndianToNative using a buffer slice?

reply "Lucas Burson" <ljdelight+dlang gmail.com> writes:
I'm trying to create a primitive type given a specific buffer 
slice. I can place the uint into a sliced buffer but I'm getting 
compiler errors when using a slice to create the uint. Still new 
to Dlang and unfamiliar with the template system.

How do I get this working?

import std.bitmanip;
int main()
{
    size_t offset = 3;
    ubyte[10] buffer;
    buffer[offset..offset+4] = nativeToBigEndian!uint(cast(uint) 
104387);

    // compiler error
    uint fromBuf = 
bigEndianToNative!uint(buffer[offset..offset+4]);
    return 0;
}

The compiler error:
./test.d(11): Error: template std.bitmanip.bigEndianToNative does 
not match any function template declaration. Candidates are:
/usr/include/dmd/phobos/std/bitmanip.d(1689):        
std.bitmanip.bigEndianToNative(T, ulong n)(ubyte[n] val) if 
(canSwapEndianness!(T) && n == T.sizeof)
./test.d(11): Error: template std.bitmanip.bigEndianToNative(T, 
ulong n)(ubyte[n] val) if (canSwapEndianness!(T) && n == 
T.sizeof) cannot deduce template function from argument types 
!(uint)(ubyte[])
./test.d(11): Error: template instance bigEndianToNative!(uint) 
errors instantiating template
Oct 21 2014
next sibling parent reply ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Wed, 22 Oct 2014 00:45:17 +0000
Lucas Burson via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:

 I'm trying to create a primitive type given a specific buffer=20
 slice. I can place the uint into a sliced buffer but I'm getting=20
 compiler errors when using a slice to create the uint. Still new=20
 to Dlang and unfamiliar with the template system.
=20
 How do I get this working?
the short answer: uint fromBuf =3D bigEndianToNative!uint(cast(ubyte[4])buffer[offset..offset+4]); the long answer: you are passing dynamic array, and function is expecting static array. slices are always dynamic by nature, so they must be casted to static arrays before passing to bigEndianToNative. 'ubyte[4]' is not a "recomendation", it means "only static arrays will do". dynamic arrays are pointer to hidden "array structure" generated by compiler, which looks like this: `struct { size_t length; void* ptr; }`. but static arrays are just direct pointers to data, there is no need to keep separate length, as it is known in compile time. by casting dynamic array/slice to static array you are telling the compiler "i know the length of the data right now, so you can use direct pointer". sorry if my explanations appears complex and hard to understand -- that's 'cause i'm not very good in teaching. but at least i tried and gave the short answer too. ;-)
Oct 21 2014
parent reply "Lucas Burson" <ljdelight+dlang gmail.com> writes:
On Wednesday, 22 October 2014 at 01:08:52 UTC, ketmar via 
Digitalmars-d-learn wrote:
 the short answer:

  uint fromBuf =
  bigEndianToNative!uint(cast(ubyte[4])buffer[offset..offset+4]);
ketmar, we meet again! Your explanation is great and that solved my problem. Thank you. Maybe I'll try out templates next...
Oct 21 2014
parent ketmar via Digitalmars-d-learn <digitalmars-d-learn puremagic.com> writes:
On Wed, 22 Oct 2014 01:30:48 +0000
Lucas Burson via Digitalmars-d-learn
<digitalmars-d-learn puremagic.com> wrote:

 ketmar, we meet again! Your explanation is great and that solved=20
 my problem. Thank you. Maybe I'll try out templates next...
yep, i remember. i was glad to help you. ;-)
Oct 21 2014
prev sibling parent "Jonathan M Davis" <jmdavisProg gmx.com> writes:
On Wednesday, October 22, 2014 00:45:17 Lucas Burson via 
Digitalmars-d-learn
wrote:
 I'm trying to create a primitive type given a specific buffer
 slice. I can place the uint into a sliced buffer but I'm getting
 compiler errors when using a slice to create the uint. Still new
 to Dlang and unfamiliar with the template system.

 How do I get this working?

 import std.bitmanip;
 int main()
 {
     size_t offset = 3;
     ubyte[10] buffer;
     buffer[offset..offset+4] = nativeToBigEndian!uint(cast(uint)
 104387);

     // compiler error
     uint fromBuf =
 bigEndianToNative!uint(buffer[offset..offset+4]);
     return 0;
 }

 The compiler error:
 ./test.d(11): Error: template std.bitmanip.bigEndianToNative 
 does
 not match any function template declaration. Candidates are:
 /usr/include/dmd/phobos/std/bitmanip.d(1689):
 std.bitmanip.bigEndianToNative(T, ulong n)(ubyte[n] val) if
 (canSwapEndianness!(T) && n == T.sizeof)
 ./test.d(11): Error: template std.bitmanip.bigEndianToNative(T,
 ulong n)(ubyte[n] val) if (canSwapEndianness!(T) && n ==
 T.sizeof) cannot deduce template function from argument types
 !(uint)(ubyte[])
 ./test.d(11): Error: template instance bigEndianToNative!(uint)
 errors instantiating template
You can't just use a dynamic array as a static array, because they're distinct types. Slicing a static array gives you a dynamic one which refers to the static array's memory, but to convert a dynamic array to a static one, you have to cast it (which will do a copy). So, your code becomes something like import std.bitmanip; void main() { size_t offset = 3; ubyte[10] buffer; buffer[offset..offset+4] = nativeToBigEndian!uint(104387); // compiler error auto fromBuf = bigEndianToNative!uint(cast(ubyte[4])buffer[offset..offset+4]); } However, in this case, you should probably just not use a dynamic array. It buys you nothing. You might as well just do. import std.bitmanip; void main() { auto buffer = nativeToBigEndian!uint(104387); // compiler error auto fromBuf = bigEndianToNative!uint(buffer); } though obviously, your actual code may be doing something more complicated that actually makes using the dynamic array reasonable. Regardless, dynamic arrays must be cast to static arrays if you want to use a dynamic array where a static array is required. - Jonathan M Davis
Oct 21 2014