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.

140 lines
7.1 KiB

  1. using IPA.Config.Data;
  2. using System;
  3. namespace IPA.Config.Stores.Converters
  4. {
  5. /// <summary>
  6. /// A <see cref="ValueConverter{T}"/> for objects normally serialized to config via <see cref="GeneratedStore.Generated{T}(Config, bool)"/>.
  7. /// </summary>
  8. /// <typeparam name="T">the same type parameter that would be passed into <see cref="GeneratedStore.Generated{T}(Config, bool)"/></typeparam>
  9. /// <seealso cref="GeneratedStore.Generated{T}(Config, bool)"/>
  10. public class CustomObjectConverter<T> : ValueConverter<T> where T : class
  11. {
  12. private interface IImpl
  13. {
  14. T FromValue(Value value, object parent);
  15. Value ToValue(T obj, object parent);
  16. }
  17. private class Impl<U> : IImpl where U : class, GeneratedStoreImpl.IGeneratedStore<T>, T
  18. {
  19. private static readonly GeneratedStoreImpl.GeneratedStoreCreator creator = GeneratedStoreImpl.GetCreator(typeof(T));
  20. private static U Create(GeneratedStoreImpl.IGeneratedStore parent)
  21. => creator(parent) as U;
  22. public T FromValue(Value value, object parent)
  23. { // lots of casting here, but it works i promise (probably) (parent can be a non-IGeneratedStore, however it won't necessarily behave then)
  24. var obj = Create(parent as GeneratedStoreImpl.IGeneratedStore);
  25. obj.Deserialize(value);
  26. return obj;
  27. }
  28. public Value ToValue(T obj, object parent)
  29. {
  30. if (obj is GeneratedStoreImpl.IGeneratedStore store)
  31. return store.Serialize();
  32. else
  33. {
  34. var newObj = Create(null);
  35. newObj.CopyFrom(obj, false); // don't use lock because it won't be used
  36. return newObj.Serialize();
  37. }
  38. }
  39. }
  40. private static readonly IImpl impl = (IImpl)Activator.CreateInstance(
  41. typeof(Impl<>).MakeGenericType(typeof(T), GeneratedStoreImpl.GetGeneratedType(typeof(T))));
  42. /// <summary>
  43. /// Deserializes <paramref name="value"/> into a <typeparamref name="T"/> with the given <paramref name="parent"/>.
  44. /// </summary>
  45. /// <param name="value">the <see cref="Value"/> to deserialize</param>
  46. /// <param name="parent">the parent object that will own the deserialized value</param>
  47. /// <returns>the deserialized value</returns>
  48. /// <seealso cref="ValueConverter{T}.FromValue(Value, object)"/>
  49. public static T Deserialize(Value value, object parent)
  50. => impl.FromValue(value, parent);
  51. /// <summary>
  52. /// Serializes <paramref name="obj"/> into a <see cref="Value"/> structure, given <paramref name="parent"/>.
  53. /// </summary>
  54. /// <param name="obj">the object to serialize</param>
  55. /// <param name="parent">the parent object that owns <paramref name="obj"/></param>
  56. /// <returns>the <see cref="Value"/> tree that represents <paramref name="obj"/></returns>
  57. /// <seealso cref="ValueConverter{T}.ToValue(T, object)"/>
  58. public static Value Serialize(T obj, object parent)
  59. => impl.ToValue(obj, parent);
  60. /// <summary>
  61. /// Deserializes <paramref name="value"/> into a <typeparamref name="T"/> with the given <paramref name="parent"/>.
  62. /// </summary>
  63. /// <param name="value">the <see cref="Value"/> to deserialize</param>
  64. /// <param name="parent">the parent object that will own the deserialized value</param>
  65. /// <returns>the deserialized value</returns>
  66. /// <seealso cref="ValueConverter{T}.FromValue(Value, object)"/>
  67. public override T FromValue(Value value, object parent)
  68. => Deserialize(value, parent);
  69. /// <summary>
  70. /// Serializes <paramref name="obj"/> into a <see cref="Value"/> structure, given <paramref name="parent"/>.
  71. /// </summary>
  72. /// <param name="obj">the object to serialize</param>
  73. /// <param name="parent">the parent object that owns <paramref name="obj"/></param>
  74. /// <returns>the <see cref="Value"/> tree that represents <paramref name="obj"/></returns>
  75. /// <seealso cref="ValueConverter{T}.ToValue(T, object)"/>
  76. public override Value ToValue(T obj, object parent)
  77. => Serialize(obj, parent);
  78. }
  79. /// <summary>
  80. /// A <see cref="ValueConverter{T}"/> for custom value types, serialized identically to the reference types serialized with
  81. /// <see cref="GeneratedStore.Generated{T}(Config, bool)"/>.
  82. /// </summary>
  83. /// <typeparam name="T">the type of the value to convert</typeparam>
  84. public class CustomValueTypeConverter<T> : ValueConverter<T> where T : struct
  85. {
  86. private static readonly GeneratedStoreImpl.SerializeObject<T> serialize
  87. = GeneratedStoreImpl.GetSerializerDelegate<T>();
  88. private static readonly GeneratedStoreImpl.DeserializeObject<T> deserialize
  89. = GeneratedStoreImpl.GetDeserializerDelegate<T>();
  90. /// <summary>
  91. /// Deserializes <paramref name="value"/> into a <typeparamref name="T"/> with the given <paramref name="parent"/>.
  92. /// </summary>
  93. /// <param name="value">the <see cref="Value"/> to deserialize</param>
  94. /// <param name="parent">the parent object that will own the deserialized value</param>
  95. /// <returns>the deserialized value</returns>
  96. /// <seealso cref="ValueConverter{T}.FromValue(Value, object)"/>
  97. public static T Deserialize(Value value, object parent)
  98. => deserialize(value, parent);
  99. /// <summary>
  100. /// Serializes <paramref name="obj"/> into a corresponding <see cref="Value"/> structure.
  101. /// </summary>
  102. /// <param name="obj">the object to serialize</param>
  103. /// <returns>the <see cref="Value"/> tree that represents <paramref name="obj"/></returns>
  104. /// <seealso cref="ValueConverter{T}.ToValue(T, object)"/>
  105. public static Value Serialize(T obj)
  106. => serialize(obj);
  107. /// <summary>
  108. /// Deserializes <paramref name="value"/> into a <typeparamref name="T"/> with the given <paramref name="parent"/>.
  109. /// </summary>
  110. /// <param name="value">the <see cref="Value"/> to deserialize</param>
  111. /// <param name="parent">the parent object that will own the deserialized value</param>
  112. /// <returns>the deserialized value</returns>
  113. /// <seealso cref="ValueConverter{T}.FromValue(Value, object)"/>
  114. public override T FromValue(Value value, object parent)
  115. => Deserialize(value, parent);
  116. /// <summary>
  117. /// Serializes <paramref name="obj"/> into a <see cref="Value"/> structure, given <paramref name="parent"/>.
  118. /// </summary>
  119. /// <param name="obj">the object to serialize</param>
  120. /// <param name="parent">the parent object that owns <paramref name="obj"/></param>
  121. /// <returns>the <see cref="Value"/> tree that represents <paramref name="obj"/></returns>
  122. /// <seealso cref="ValueConverter{T}.ToValue(T, object)"/>
  123. public override Value ToValue(T obj, object parent)
  124. => Serialize(obj);
  125. }
  126. }