DFStorage.cs 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262
  1. using Newtonsoft.Json.Linq;
  2. using System;
  3. using System.Collections.Generic;
  4. using System.Diagnostics.CodeAnalysis;
  5. using System.Linq;
  6. namespace InABox.Core
  7. {
  8. /// <summary>
  9. /// Class to manage the storing of form data, including the separation of blob and form data.
  10. /// </summary>
  11. public class DFSaveStorage
  12. {
  13. public Dictionary<string, object?> FormData { get; private set; }
  14. public Dictionary<string, object?> BlobData { get; private set; }
  15. public DFSaveStorage()
  16. {
  17. FormData = new Dictionary<string, object?>();
  18. BlobData = new Dictionary<string, object?>();
  19. }
  20. public int Count() => FormData.Count();
  21. public void AddValue(string key, object? value)
  22. {
  23. FormData.Add(key, value);
  24. }
  25. public void AddBlobValue(string key, object? value)
  26. {
  27. if(value != null)
  28. {
  29. var id = Guid.NewGuid().ToString();
  30. BlobData.Add(id, value);
  31. FormData.Add(key, id);
  32. }
  33. }
  34. public object? GetValue(string key) => FormData.GetValueOrDefault(key);
  35. public DFSaveStorageEntry GetEntry(string key)
  36. {
  37. return new DFSaveStorageEntry(this, key);
  38. }
  39. public DFLoadStorage ToLoadStorage()
  40. {
  41. return new DFLoadStorage(FormData, BlobData);
  42. }
  43. }
  44. public class DFSaveStorageEntry
  45. {
  46. private readonly DFSaveStorage storage;
  47. private readonly string key;
  48. public DFSaveStorageEntry(DFSaveStorage storage, string key)
  49. {
  50. this.storage = storage;
  51. this.key = key;
  52. }
  53. public object? GetValue() => storage.GetValue(key);
  54. public object? GetValue(string subKey) => storage.GetValue($"{key}.{subKey}");
  55. public void SetValue(object? value)
  56. {
  57. storage.AddValue(key, value);
  58. }
  59. public void AddValue(string subKey, object? value)
  60. {
  61. storage.AddValue($"{key}.{subKey}", value);
  62. }
  63. public void SetBlobValue(object? value)
  64. {
  65. storage.AddBlobValue(key, value);
  66. }
  67. public void AddBlobValue(string subKey, object? value)
  68. {
  69. storage.AddBlobValue($"{key}.{subKey}", value);
  70. }
  71. }
  72. public class DFLoadStorage
  73. {
  74. public Dictionary<string, object?> FormData { get; private set; } = new Dictionary<string, object?>();
  75. public DFLoadStorage() : this(new Dictionary<string, object?>(), null)
  76. {
  77. }
  78. public DFLoadStorage(Dictionary<string, object?> formData, Dictionary<string, object?>? blobData)
  79. {
  80. Load(formData, blobData);
  81. }
  82. public void Load(Dictionary<string, object?> formData, Dictionary<string, object?>? blobData)
  83. {
  84. FormData = formData;
  85. if (blobData != null)
  86. {
  87. var updates = new List<Tuple<string, object?>>();
  88. foreach (var (key, value) in FormData)
  89. {
  90. if ((value is string str && blobData.TryGetValue(str, out var blob))
  91. || (value is Guid guid && blobData.TryGetValue(guid.ToString(), out blob)))
  92. {
  93. updates.Add(new Tuple<string, object?>(key, blob));
  94. }
  95. }
  96. foreach (var (key, value) in updates)
  97. {
  98. FormData[key] = value;
  99. }
  100. }
  101. }
  102. public void Clear() => FormData.Clear();
  103. public int Count() => FormData.Count();
  104. /// <summary>
  105. /// Get a value from the storage, returning <see langword="null"/> if the key does not exist.
  106. /// </summary>
  107. /// <param name="key"></param>
  108. /// <returns></returns>
  109. public object? GetValue(string key)
  110. {
  111. return FormData.GetValueOrDefault(key);
  112. }
  113. [return: MaybeNull]
  114. public T GetValue<T>(string key)
  115. {
  116. if(FormData.TryGetValue(key, out var value))
  117. {
  118. if(value is T t)
  119. {
  120. return t;
  121. }
  122. else if(value is string str)
  123. {
  124. if(Guid.TryParse(str, out var id))
  125. {
  126. if(id is T)
  127. {
  128. return (T)(object)id;
  129. }
  130. else
  131. {
  132. return default;
  133. }
  134. }
  135. try
  136. {
  137. return Serialization.Deserialize<T>(str, strict: true);
  138. }
  139. catch
  140. {
  141. return CoreUtils.ChangeType<T>(value);
  142. }
  143. }
  144. else if(value is JToken jToken)
  145. {
  146. return Serialization.Deserialize<T>(jToken);
  147. }
  148. else
  149. {
  150. return CoreUtils.ChangeType<T>(value);
  151. }
  152. }
  153. return default;
  154. }
  155. public bool HasValue(string key)
  156. {
  157. return FormData.ContainsKey(key);
  158. }
  159. public DFLoadStorageEntry GetEntry(string key)
  160. {
  161. return new DFLoadStorageEntry(this, key);
  162. }
  163. public IEnumerable<KeyValuePair<string, object?>> Items()
  164. {
  165. return FormData;
  166. }
  167. }
  168. public class DFLoadStorageEntry
  169. {
  170. private readonly DFLoadStorage storage;
  171. private readonly string key;
  172. public DFLoadStorageEntry(DFLoadStorage storage, string key)
  173. {
  174. this.storage = storage;
  175. this.key = key;
  176. }
  177. /// <summary>
  178. /// Gets the value from the storage entry, returning <see langword="null"/> if it does not exist.
  179. /// </summary>
  180. /// <param name="key"></param>
  181. /// <returns></returns>
  182. public object? GetValue()
  183. {
  184. return storage.GetValue(key);
  185. }
  186. [return: MaybeNull]
  187. public T GetValue<T>()
  188. {
  189. return storage.GetValue<T>(key);
  190. }
  191. /// <summary>
  192. /// Gets a sub-value from the storage entry, returning <see langword="null"/> if it does not exist.
  193. /// </summary>
  194. /// <param name="subKey"></param>
  195. /// <returns></returns>
  196. public object? GetValue(string subKey)
  197. {
  198. return storage.GetValue($"{key}.{subKey}");
  199. }
  200. [return: MaybeNull]
  201. public T GetValue<T>(string subKey)
  202. {
  203. return storage.GetValue<T>($"{key}.{subKey}");
  204. }
  205. public bool HasValue() => storage.HasValue(key);
  206. public bool HasValue(string subKey) => storage.HasValue($"{key}.{subKey}");
  207. public IEnumerable<KeyValuePair<string, object?>> SubItems()
  208. {
  209. var prefix = $"{key}.";
  210. foreach(var (key, value) in storage.Items())
  211. {
  212. if (key.StartsWith(prefix))
  213. {
  214. yield return new KeyValuePair<string, object?>(key[prefix.Length..], value);
  215. }
  216. }
  217. }
  218. }
  219. }