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.

80 lines
3.3 KiB

  1. using IPA.Config.Data;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Linq;
  5. using System.Text;
  6. using System.Threading.Tasks;
  7. namespace IPA.Config.Stores.Converters
  8. {
  9. /// <summary>
  10. /// Provides utility functions for custom converters.
  11. /// </summary>
  12. public static class Converter
  13. {
  14. /// <summary>
  15. /// Gets the integral value of a <see cref="Value"/>, coercing a <see cref="FloatingPoint"/> if necessary,
  16. /// or <see langword="null"/> if <paramref name="val"/> is not an <see cref="Integer"/> or <see cref="FloatingPoint"/>.
  17. /// </summary>
  18. /// <param name="val">the <see cref="Value"/> to get the integral value of</param>
  19. /// <returns>the integral value of <paramref name="val"/>, or <see langword="null"/></returns>
  20. public static long? IntValue(Value val)
  21. => val is Integer inte ? inte.Value :
  22. val is FloatingPoint fp ? fp.AsInteger()?.Value :
  23. null;
  24. /// <summary>
  25. /// Gets the floaing point value of a <see cref="Value"/>, coercing an <see cref="Integer"/> if necessary,
  26. /// or <see langword="null"/> if <paramref name="val"/> is not an <see cref="Integer"/> or <see cref="FloatingPoint"/>.
  27. /// </summary>
  28. /// <param name="val">the <see cref="Value"/> to get the floaing point value of</param>
  29. /// <returns>the floaing point value of <paramref name="val"/>, or <see langword="null"/></returns>
  30. public static decimal? FloatValue(Value val)
  31. => val is FloatingPoint fp ? fp.Value :
  32. val is Integer inte ? inte.AsFloat()?.Value :
  33. null;
  34. }
  35. public class CustomObjectConverter<T> : ValueConverter<T> where T : class
  36. {
  37. private interface IImpl
  38. {
  39. T FromValue(Value value, object parent);
  40. Value ToValue(T obj, object parent);
  41. }
  42. private class Impl<U> : IImpl where U : class, GeneratedStore.IGeneratedStore, T
  43. {
  44. private static readonly GeneratedStore.GeneratedStoreCreator creator = GeneratedStore.GetCreator(typeof(T));
  45. public T FromValue(Value value, object parent)
  46. { // lots of casting here, but it works i promise
  47. var obj = creator(parent as GeneratedStore.IGeneratedStore) as U;
  48. obj.Deserialize(value);
  49. return obj;
  50. }
  51. public Value ToValue(T obj, object parent)
  52. {
  53. if (obj is GeneratedStore.IGeneratedStore store)
  54. return store.Serialize();
  55. else
  56. return null; // TODO: make this behave sanely instead of just giving null
  57. }
  58. }
  59. private static readonly IImpl impl = (IImpl)Activator.CreateInstance(
  60. typeof(Impl<>).MakeGenericType(GeneratedStore.GetGeneratedType(typeof(T))));
  61. public static T Deserialize(Value value, object parent)
  62. => impl.FromValue(value, parent);
  63. public static Value Serialize(T obj, object parent)
  64. => impl.ToValue(obj, parent);
  65. public override T FromValue(Value value, object parent)
  66. => impl.FromValue(value, parent);
  67. public override Value ToValue(T obj, object parent)
  68. => impl.ToValue(obj, parent);
  69. }
  70. }