Skip to content

Commit

Permalink
Fix endianess handling for streams
Browse files Browse the repository at this point in the history
  • Loading branch information
LunaTheFoxgirl committed Oct 9, 2024
1 parent 52cc5db commit c73e820
Show file tree
Hide file tree
Showing 3 changed files with 73 additions and 21 deletions.
38 changes: 21 additions & 17 deletions source/numem/io/endian.d
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ module numem.io.endian;
import numem.core;
import numem.collections.vector;
import std.traits : isNumeric, isIntegral, isBasicType;
import std.traits : Unqual;
import std.bitmanip;

@nogc nothrow:

Expand Down Expand Up @@ -58,21 +60,21 @@ private {
*/
@trusted
ubyte[T.sizeof] toEndian(T)(T value, Endianess endianness) {
union tmp {
Unqual!T value;
ubyte[T.sizeof] bytes;
}

// Get bytes from value
ubyte[T.sizeof] output;
output = (cast(ubyte*)&value)[0..T.sizeof];
tmp tmp_;
tmp_.value = value;

// Swap endianness if neccesary
if (endianness != NATIVE_ENDIAN) {
ubyte[T.sizeof] tmp;
static foreach (i; 0..T.sizeof) {
tmp[i] = output[(T.sizeof-1)-i];
}
output = tmp;
ubyte[] slice = tmp_.bytes[0..$];
swapEndian(slice);
}

return output;
return tmp_.bytes;
}

/**
Expand All @@ -88,9 +90,9 @@ T toEndianReinterpret(T)(T in_, Endianess endianness) {
ubyte[T.sizeof] bytes;
}

tmp toConvert;
toConvert.bytes = toEndian!T(in_, endianness);
return toConvert.value;
tmp tmp_;
tmp_.bytes = toEndian!T(in_, endianness);
return tmp_.value;
}

return in_;
Expand All @@ -107,13 +109,14 @@ T fromEndian(T)(ubyte[] value, Endianess endianness) if (isBasicType!T) {
T value;
ubyte[T.sizeof] bytes;
}
tmp toConvert;
toConvert.bytes = value;
tmp tmp_;
tmp_.bytes = value;
ubyte[] slice = tmp_.bytes[0..$];

if (endianness != NATIVE_ENDIAN)
swapEndian(value);
swapEndian(slice);

return toConvert.value;
return tmp_.value;
}

/**
Expand All @@ -130,9 +133,10 @@ T fromEndianReinterpret(T)(ubyte[] value, Endianess endianness) {
}
tmp toConvert;
toConvert.bytes = value;
ubyte[] slice = tmp_.bytes[0..$];

if (endianness != NATIVE_ENDIAN)
swapEndian(value);
swapEndian(slice);

return toConvert.value;
}
Expand Down
2 changes: 1 addition & 1 deletion source/numem/io/stream/reader.d
Original file line number Diff line number Diff line change
Expand Up @@ -86,7 +86,7 @@ public:
static if (is(T.valueType == ubyte)) {
r += stream.read(val, 0, length);
} else {
T tmp;
T.valueType tmp;
foreach(i; 0..length) {
int ir = this.read!(T.valueType)(tmp);
if (ir < 0)
Expand Down
54 changes: 51 additions & 3 deletions source/numem/io/stream/writer.d
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ public:
stream.write(toWrite);
} else {
ubyte[1] tmp = [cast(ubyte)val];

stream.write(tmp[]);
}
}
Expand All @@ -53,8 +52,12 @@ public:
/// Ditto
@trusted
void write(T)(T val) if (isSomeVector!T) {
foreach(element; val) {
this.write!(T.valueType)(element);
static if (T.valueType.sizeof == 1) {
stream.write(cast(ubyte[])val[0..$]);
} else {
foreach(element; val) {
this.write!(T.valueType)(element);
}
}
}

Expand All @@ -81,4 +84,49 @@ unittest {

assert(buffer[0] == 100);
assert(buffer[99] == 1);
}

@("RW: Little Endian")
unittest {
import numem.io.stream.memstream : MemoryStream;
import numem.io.stream.reader : StreamReader;
alias TestReader = StreamReader!(Endianess.littleEndian);
alias TestWriter = StreamWriter!(Endianess.littleEndian);

ubyte[8] buffer;
auto stream = new MemoryStream(buffer.ptr, buffer.length);
auto writer = new TestWriter(stream);
auto reader = new TestReader(stream);

enum MAGIC = 0xFF00FF0F;

writer.write!ulong(MAGIC);
stream.seek(0);

ulong val;
reader.read!ulong(val);

assert(val == MAGIC);
}

@("RW: Big Endian")
unittest {
import numem.io.stream.memstream : MemoryStream;
import numem.io.stream.reader : StreamReader;
alias TestReader = StreamReader!(Endianess.bigEndian);
alias TestWriter = StreamWriter!(Endianess.bigEndian);

ubyte[8] buffer;
auto stream = new MemoryStream(buffer.ptr, buffer.length);
auto writer = new TestWriter(stream);
auto reader = new TestReader(stream);

enum MAGIC = 0xFF00FF0F;

writer.write!ulong(MAGIC);
stream.seek(0);

ulong val;
reader.read!ulong(val);
assert(val == MAGIC);
}

0 comments on commit c73e820

Please sign in to comment.