#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())}}}";
}
}