81 lines
2.0 KiB
C#
81 lines
2.0 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
using System.Runtime.InteropServices;
|
|
using System.Text;
|
|
using System.Threading.Tasks;
|
|
|
|
namespace skyscraper5.DNS.Protocol.Marshalling
|
|
{
|
|
internal class Struct
|
|
{
|
|
public static T GetStruct<T>(byte[] data, int offset, int length) where T : struct
|
|
{
|
|
byte[] buffer = new byte[length];
|
|
Array.Copy(data, offset, buffer, 0, buffer.Length);
|
|
|
|
GCHandle handle = GCHandle.Alloc(ConvertEndian<T>(buffer), GCHandleType.Pinned);
|
|
|
|
try
|
|
{
|
|
return Marshal.PtrToStructure<T>(handle.AddrOfPinnedObject());
|
|
}
|
|
finally
|
|
{
|
|
handle.Free();
|
|
}
|
|
}
|
|
|
|
private static byte[] ConvertEndian<T>(byte[] data)
|
|
{
|
|
Type type = typeof(T);
|
|
FieldInfo[] fields = type.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
|
EndianAttribute endian = null;
|
|
|
|
if (type.GetTypeInfo().IsDefined(typeof(EndianAttribute), false))
|
|
{
|
|
endian = (EndianAttribute)type.GetTypeInfo().GetCustomAttributes(typeof(EndianAttribute), false).First();
|
|
}
|
|
|
|
foreach (FieldInfo field in fields)
|
|
{
|
|
if (endian == null && !field.IsDefined(typeof(EndianAttribute), false))
|
|
{
|
|
continue;
|
|
}
|
|
|
|
int offset = Marshal.OffsetOf<T>(field.Name).ToInt32();
|
|
#pragma warning disable 618
|
|
int length = Marshal.SizeOf(field.FieldType);
|
|
#pragma warning restore 618
|
|
endian = endian ?? (EndianAttribute)field.GetCustomAttributes(typeof(EndianAttribute), false).First();
|
|
|
|
if (endian.Endianness == Endianness.Big && BitConverter.IsLittleEndian ||
|
|
endian.Endianness == Endianness.Little && !BitConverter.IsLittleEndian)
|
|
{
|
|
Array.Reverse(data, offset, length);
|
|
}
|
|
}
|
|
|
|
return data;
|
|
}
|
|
|
|
public static byte[] GetBytes<T>(T obj) where T : struct
|
|
{
|
|
byte[] data = new byte[Marshal.SizeOf(obj)];
|
|
GCHandle handle = GCHandle.Alloc(data, GCHandleType.Pinned);
|
|
|
|
try
|
|
{
|
|
Marshal.StructureToPtr(obj, handle.AddrOfPinnedObject(), false);
|
|
return ConvertEndian<T>(data);
|
|
}
|
|
finally
|
|
{
|
|
handle.Free();
|
|
}
|
|
}
|
|
}
|
|
}
|