Mirror of Svelto.ECS because we're a fan of it
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

89 lines
3.5KB

  1. using System;
  2. using System.Reflection;
  3. using System.Runtime.InteropServices;
  4. using Svelto.DataStructures;
  5. using Attribute = System.Attribute;
  6. namespace Svelto.ECS.Serialization
  7. {
  8. [AttributeUsage(AttributeTargets.Field)]
  9. public class PartialSerializerFieldAttribute : Attribute
  10. {}
  11. public class PartialSerializer<T> : ISerializer<T>
  12. where T : unmanaged, IEntityStruct
  13. {
  14. static PartialSerializer()
  15. {
  16. Type myType = typeof(T);
  17. FieldInfo[] myMembers = myType.GetFields();
  18. for (int i = 0; i < myMembers.Length; i++)
  19. {
  20. Object[] myAttributes = myMembers[i].GetCustomAttributes(true);
  21. for (int j = 0; j < myAttributes.Length; j++)
  22. {
  23. if (myAttributes[j] is PartialSerializerFieldAttribute)
  24. {
  25. if (myMembers[i].FieldType == typeof(EGID))
  26. throw new ECSException("EGID fields cannot be serialised ".FastConcat(myType.FullName));
  27. var offset = Marshal.OffsetOf<T>(myMembers[i].Name);
  28. var sizeOf = (uint)Marshal.SizeOf(myMembers[i].FieldType);
  29. offsets.Add(((uint) offset.ToInt32(), sizeOf));
  30. totalSize += sizeOf;
  31. }
  32. }
  33. }
  34. if (myType.GetProperties().Length > (EntityBuilder<T>.HAS_EGID ? 1 : 0))
  35. throw new ECSException("serializable entity struct must be property less ".FastConcat(myType.FullName));
  36. }
  37. public bool Serialize(in T value, ISerializationData serializationData)
  38. {
  39. unsafe
  40. {
  41. fixed (byte* dataptr = serializationData.data.ToArrayFast())
  42. {
  43. var entityStruct = value;
  44. foreach ((uint offset, uint size) offset in offsets)
  45. {
  46. byte* srcPtr = (byte*) &entityStruct + offset.offset;
  47. //todo move to Unsafe Copy when available as it is faster
  48. Buffer.MemoryCopy(srcPtr, dataptr + serializationData.dataPos,
  49. serializationData.data.Count - serializationData.dataPos, offset.size);
  50. serializationData.dataPos += offset.size;
  51. }
  52. }
  53. }
  54. return true;
  55. }
  56. public bool Deserialize(ref T value, ISerializationData serializationData)
  57. {
  58. unsafe
  59. {
  60. T tempValue = value; //todo: temporary solution I want to get rid of this copy
  61. fixed (byte* dataptr = serializationData.data.ToArrayFast())
  62. foreach ((uint offset, uint size) offset in offsets)
  63. {
  64. byte* dstPtr = (byte*) &tempValue + offset.offset;
  65. //todo move to Unsafe Copy when available as it is faster
  66. Buffer.MemoryCopy(dataptr + serializationData.dataPos, dstPtr, offset.size, offset.size);
  67. serializationData.dataPos += offset.size;
  68. }
  69. value = tempValue; //todo: temporary solution I want to get rid of this copy
  70. }
  71. return true;
  72. }
  73. public uint size => totalSize;
  74. static readonly FasterList<(uint, uint)> offsets = new FasterList<(uint, uint)>();
  75. static readonly uint totalSize;
  76. }
  77. }