#nullable enable using IPA.Utilities; using System.Collections; using System.Collections.Generic; using System.Linq; namespace IPA.Config.Data { /// /// A ordered map of to for serialization by an . /// Use or to create. /// public sealed class Map : Value, IDictionary { private readonly Dictionary values = new(); private readonly List keyOrder = new(); internal Map() { } /// /// Accesses the at in the map. /// /// the key to get the value associated with /// the value associated with the /// public Value? this[string key] { get => values[key]; set => values[key] = value; } /// /// Gets a collection of the keys for the . /// /// public ICollection Keys => keyOrder; /// /// Gets a collection of the values in the . /// /// /// Unlike all other iterables given by , this does not /// guarantee that order is maintained. /// /// public ICollection Values => values.Values; /// /// Gets the number of key-value pairs in this . /// /// public int Count => values.Count; bool ICollection>.IsReadOnly => ((IDictionary)values).IsReadOnly; /// /// Adds a new with a given key. /// /// the key to put the value at /// the to add /// public void Add(string key, Value? value) { values.Add(key, value); keyOrder.Add(key); } void ICollection>.Add(KeyValuePair item) => Add(item.Key, item.Value); /// /// Clears the of its key-value pairs. /// /// public void Clear() { values.Clear(); keyOrder.Clear(); } bool ICollection>.Contains(KeyValuePair item) => ((IDictionary)values).Contains(item); /// /// Checks if the contains a given . /// /// the key to check for /// if the key exists, otherwise /// public bool ContainsKey(string key) => values.ContainsKey(key); void ICollection>.CopyTo(KeyValuePair[] array, int arrayIndex) => ((IDictionary)values).CopyTo(array, arrayIndex); /// /// Enumerates the 's key-value pairs. /// /// an of key-value pairs in this /// public IEnumerator> GetEnumerator() { foreach (var key in keyOrder) yield return new KeyValuePair(key, this[key]); } /// /// Removes the object associated with a key in this . /// /// the key to remove /// if the key existed, otherwise /// public bool Remove(string key) => values.Remove(key) && keyOrder.Remove(key); bool ICollection>.Remove(KeyValuePair item) => ((IDictionary)values).Remove(item) && (keyOrder.Remove(item.Key) || true); /// /// Gets the value associated with the specified key. /// /// the key of the value to get /// the target location of the retrieved object /// if the key was found and set, otherwise /// public bool TryGetValue(string key, out Value? value) => values.TryGetValue(key, out value); IEnumerator IEnumerable.GetEnumerator() => GetEnumerator(); /// /// Converts this into a human-readable format. /// /// a JSON-like set of key-value pairs public override string ToString() => $"{{{string.Join(",", this.Select(p => $"\"{p.Key}\":{p.Value?.ToString() ?? "null"}").StrJP())}}}"; } }