digitalmars.D.learn - bitmanip bigEndianToNative using a buffer slice?
- Lucas Burson (29/29) Oct 21 2014 I'm trying to create a primitive type given a specific buffer
- ketmar via Digitalmars-d-learn (21/27) Oct 21 2014 On Wed, 22 Oct 2014 00:45:17 +0000
- Lucas Burson (4/7) Oct 21 2014 ketmar, we meet again! Your explanation is great and that solved
- ketmar via Digitalmars-d-learn (4/6) Oct 21 2014 On Wed, 22 Oct 2014 01:30:48 +0000
- Jonathan M Davis (39/69) Oct 21 2014 On Wednesday, October 22, 2014 00:45:17 Lucas Burson via
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
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
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
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
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 templateYou 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