// using System.Runtime.InteropServices; // using System.Linq; // using Microsoft.VisualStudio.TestTools.UnitTesting; [TestClass] public class EndianStructExtensionTests { [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct Foo { public byte b1; public short s; public ushort S; public int i; public uint I; public long l; public ulong L; public float f; public double d; [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] public string MyString; } [StructLayout(LayoutKind.Sequential, Pack = 1)] public struct FooReversed { [MarshalAs(UnmanagedType.ByValTStr, SizeConst = 10)] public string MyString; public double d; public float f; public ulong L; public long l; public uint I; public int i; public ushort S; public short s; public byte b1; } byte[] _defaultBEBytes = new byte[] { 1, 0,1, 0,1, 0,0,0,1, 0,0,0,1, 0,0,0,0,0,0,0,1, 0,0,0,0,0,0,0,1, 0x3F,0X80,0,0, // float of 1 (see http://en.wikipedia.org/wiki/Endianness#Floating-point_and_endianness) 0x3F,0xF0,0,0,0,0,0,0, // double of 1 0,0,0,0x67,0x6E,0x69,0x74,0x73,0x65,0x54 // Testing\0\0\0 }; private FooReversed GetDefaultStruct() { FooReversed f; f.b1 = 1; f.s = 1; f.S = 1; f.i = 1; f.I = 1; f.l = 1; f.L = 1; f.f = 1.0f; f.d = 1.0; f.MyString = "Testing"; return f; } [TestMethod] public void ToStructHostEndian_BEBytesOfValueOneForMostTypes_Matches() { byte[] bytes = _defaultBEBytes.Reverse().ToArray(); FooReversed expected = GetDefaultStruct(); FooReversed actual = bytes.ToStructureHostEndian(); Assert.AreEqual(expected, actual); } [TestMethod] public void ToBytesHostEndian_DefaultStruct_BytesMatch() { byte[] expected = _defaultBEBytes.Reverse().ToArray(); byte[] actual = GetDefaultStruct().ToBytesHostEndian(); CollectionAssert.AreEqual(expected,actual); } } public static class EndianExtensions { /// /// Convert the bytes to a structure in host-endian format (little-endian on PCs). /// To use with big-endian data, reverse all of the data bytes and create a struct that is in the reverse order of the data. /// /// /// The buffer. /// public static T ToStructureHostEndian(this byte[] buffer) where T : struct { GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); T stuff = (T)Marshal.PtrToStructure(handle.AddrOfPinnedObject(), typeof(T)); handle.Free(); return stuff; } /// /// Converts the struct to a byte array in the endianness of this machine. /// /// /// The structure. /// public static byte[] ToBytesHostEndian(this T structure) where T : struct { int size = Marshal.SizeOf(structure); var buffer = new byte[size]; GCHandle handle = GCHandle.Alloc(buffer, GCHandleType.Pinned); Marshal.StructureToPtr(structure, handle.AddrOfPinnedObject(), true); handle.Free(); return buffer; } }