// Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. namespace Microsoft.Teams.Common.Storage; /// /// a local in-memory `IStorage` implementation /// /// the value type public class LocalStorage : IStorage { protected Dictionary _store = []; protected IList _keys = []; protected int? _max; /// /// the number of items in the storage /// public int Size => _store.Count; /// /// get the list of storage keys /// public IList Keys => _store.Keys.ToList(); public LocalStorage(int? max = null) { _max = max; } public LocalStorage(IDictionary data, int? max) { _store = new Dictionary(data); _keys = data.Keys.ToList(); _max = max; } public bool Exists(string key) => _store.ContainsKey(key); public Task ExistsAsync(string key) => Task.FromResult(Exists(key)); public TValue? Get(string key) { Hit(key); return _store.TryGetValue(key, out var value) ? value : default; } public T? Get(string key) where T : TValue { var value = Get(key); return (T?)value; } public Task GetAsync(string key) { return Task.FromResult(Get(key)); } public async Task GetAsync(string key) where T : TValue { var value = await GetAsync(key).ConfigureAwait(false); return (T?)value; } public void Set(string key, TValue value) { if (!Hit(key)) _keys.Add(key); if (_max is not null) { if (_keys.Count > _max) { var toRemove = _keys.ElementAt(0); _keys.RemoveAt(0); _store.Remove(toRemove); } } _store[key] = value; } public Task SetAsync(string key, TValue value) { Set(key, value); return Task.CompletedTask; } public void Delete(string key) { var index = _keys.IndexOf(key); if (index == -1) return; _keys.RemoveAt(index); _store.Remove(key); } public Task DeleteAsync(string key) { Delete(key); return Task.CompletedTask; } protected bool Hit(string key) { if (!Exists(key)) return false; if (Keys.Last() == key) return true; var index = _keys.IndexOf(key); if (index < 0) return false; for (var i = index + 1; i < _keys.Count; i++) { var tmp = _keys[i - 1]; _keys[i - 1] = _keys[i]; _keys[i] = tmp; } return true; } }