using System; using System.Collections.Concurrent; using System.Collections.Generic; using System.IO; using System.Threading.Tasks; using static System.Text.Json.JsonSerializer; namespace AnotherReplayReader { internal sealed class Cache { public static string CacheDirectory => Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "RA3Bar.Lanyi.AnotherReplayReader"); public static string CacheFilePath => Path.Combine(CacheDirectory, "AnotherReplayReader.cache"); private readonly ConcurrentDictionary _storage = new(); public Task Initialization { get; } public Cache() { Initialization = Task.Run(async () => { try { if (!Directory.Exists(CacheDirectory)) { Directory.CreateDirectory(CacheDirectory); } using var cacheStream = File.OpenRead(CacheFilePath); var futureCache = DeserializeAsync>(cacheStream).ConfigureAwait(false); if (await futureCache is not { } cached) { return; } foreach (var kv in cached) { _storage.TryAdd(kv.Key, kv.Value); } } catch { } }); } public T GetOrDefault(string key, in T defaultValue) { try { if (_storage.TryGetValue(key, out var valueString)) { return Deserialize(valueString) ?? defaultValue; } } catch { } return defaultValue; } public void Set(string key, in T value) { try { _storage[key] = Serialize(value); Save(); } catch { } } public void SetValues(params (string Key, object Value)[] values) { try { foreach (var (key, value) in values) { _storage[key] = Serialize(value); } Save(); } catch { } } public void Remove(string key) { _storage.TryRemove(key, out _); Save(); } public async void Save() { try { using var cacheStream = File.Open(CacheFilePath, FileMode.Create, FileAccess.Write); await SerializeAsync(cacheStream, _storage).ConfigureAwait(false); } catch { } } } }