TomlTypeConverter.cs 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Globalization;
  4. namespace BepInEx.Configuration
  5. {
  6. /// <summary>
  7. /// Serializer/deserializer used by the config system.
  8. /// </summary>
  9. public static class TomlTypeConverter
  10. {
  11. private static Dictionary<Type, TypeConverter> TypeConverters { get; } = new Dictionary<Type, TypeConverter>
  12. {
  13. [typeof(string)] = new TypeConverter
  14. {
  15. ConvertToString = (obj, type) => (string)obj,
  16. ConvertToObject = (str, type) => str,
  17. },
  18. [typeof(bool)] = new TypeConverter
  19. {
  20. ConvertToString = (obj, type) => obj.ToString().ToLowerInvariant(),
  21. ConvertToObject = (str, type) => bool.Parse(str),
  22. },
  23. [typeof(byte)] = new TypeConverter
  24. {
  25. ConvertToString = (obj, type) => obj.ToString(),
  26. ConvertToObject = (str, type) => byte.Parse(str),
  27. },
  28. //integral types
  29. [typeof(sbyte)] = new TypeConverter
  30. {
  31. ConvertToString = (obj, type) => obj.ToString(),
  32. ConvertToObject = (str, type) => sbyte.Parse(str),
  33. },
  34. [typeof(byte)] = new TypeConverter
  35. {
  36. ConvertToString = (obj, type) => obj.ToString(),
  37. ConvertToObject = (str, type) => byte.Parse(str),
  38. },
  39. [typeof(short)] = new TypeConverter
  40. {
  41. ConvertToString = (obj, type) => obj.ToString(),
  42. ConvertToObject = (str, type) => short.Parse(str),
  43. },
  44. [typeof(ushort)] = new TypeConverter
  45. {
  46. ConvertToString = (obj, type) => obj.ToString(),
  47. ConvertToObject = (str, type) => ushort.Parse(str),
  48. },
  49. [typeof(int)] = new TypeConverter
  50. {
  51. ConvertToString = (obj, type) => obj.ToString(),
  52. ConvertToObject = (str, type) => int.Parse(str),
  53. },
  54. [typeof(uint)] = new TypeConverter
  55. {
  56. ConvertToString = (obj, type) => obj.ToString(),
  57. ConvertToObject = (str, type) => uint.Parse(str),
  58. },
  59. [typeof(long)] = new TypeConverter
  60. {
  61. ConvertToString = (obj, type) => obj.ToString(),
  62. ConvertToObject = (str, type) => long.Parse(str),
  63. },
  64. [typeof(ulong)] = new TypeConverter
  65. {
  66. ConvertToString = (obj, type) => obj.ToString(),
  67. ConvertToObject = (str, type) => ulong.Parse(str),
  68. },
  69. //floating point types
  70. [typeof(float)] = new TypeConverter
  71. {
  72. ConvertToString = (obj, type) => ((float)obj).ToString(NumberFormatInfo.InvariantInfo),
  73. ConvertToObject = (str, type) => float.Parse(str, NumberFormatInfo.InvariantInfo),
  74. },
  75. [typeof(double)] = new TypeConverter
  76. {
  77. ConvertToString = (obj, type) => ((double)obj).ToString(NumberFormatInfo.InvariantInfo),
  78. ConvertToObject = (str, type) => double.Parse(str, NumberFormatInfo.InvariantInfo),
  79. },
  80. [typeof(decimal)] = new TypeConverter
  81. {
  82. ConvertToString = (obj, type) => ((decimal)obj).ToString(NumberFormatInfo.InvariantInfo),
  83. ConvertToObject = (str, type) => decimal.Parse(str, NumberFormatInfo.InvariantInfo),
  84. },
  85. //enums are special
  86. [typeof(Enum)] = new TypeConverter
  87. {
  88. ConvertToString = (obj, type) => obj.ToString(),
  89. ConvertToObject = (str, type) => Enum.Parse(type, str, true),
  90. },
  91. };
  92. public static string ConvertToString(object value, Type valueType)
  93. {
  94. var conv = GetConverter(valueType);
  95. if (conv == null)
  96. throw new InvalidOperationException($"Cannot convert from type {valueType}");
  97. return conv.ConvertToString(value, valueType);
  98. }
  99. public static T ConvertToValue<T>(string value)
  100. {
  101. return (T)ConvertToValue(value, typeof(T));
  102. }
  103. public static object ConvertToValue(string value, Type valueType)
  104. {
  105. var conv = GetConverter(valueType);
  106. if (conv == null)
  107. throw new InvalidOperationException($"Cannot convert to type {valueType.Name}");
  108. return conv.ConvertToObject(value, valueType);
  109. }
  110. public static TypeConverter GetConverter(Type valueType)
  111. {
  112. if (valueType == null) throw new ArgumentNullException(nameof(valueType));
  113. if (valueType.IsEnum)
  114. return TypeConverters[typeof(Enum)];
  115. TypeConverters.TryGetValue(valueType, out var result);
  116. return result;
  117. }
  118. public static void AddConverter(Type type, TypeConverter converter)
  119. {
  120. if (type == null) throw new ArgumentNullException(nameof(type));
  121. if (converter == null) throw new ArgumentNullException(nameof(converter));
  122. if (CanConvert(type)) throw new ArgumentException("The specified type already has a converter assigned to it", nameof(type));
  123. TypeConverters.Add(type, converter);
  124. }
  125. public static bool CanConvert(Type type)
  126. {
  127. return GetConverter(type) != null;
  128. }
  129. public static IEnumerable<Type> GetSupportedTypes()
  130. {
  131. return TypeConverters.Keys;
  132. }
  133. }
  134. }