#nullable enable using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using IPA.Config.Data; using IPA.Logging; namespace IPA.Config.Stores.Converters { /// /// A base class for all type converters, providing most of the functionality. /// /// the type of the items in the collection /// the instantiated type of collection public class CollectionConverter : ValueConverter where TCollection : ICollection { /// /// Creates a using the default converter for the /// element type. Equivalent to calling /// with . /// /// public CollectionConverter() : this(Converter.Default) { } /// /// Creates a using the specified underlying converter. /// /// the to use to convert the values public CollectionConverter(ValueConverter underlying) => BaseConverter = underlying; /// /// Gets the converter for the collection's value type. /// protected ValueConverter BaseConverter { get; } /// /// Creates a collection of type using the and /// . /// /// the initial size of the collecion /// the object that will own the new collection /// a new instance of /// protected virtual TCollection Create(int size, object parent) => Activator.CreateInstance(); /// /// Populates the colleciton with the deserialized values from /// with the parent . /// /// the collection to populate /// the values to populate it with /// the object that will own the new objects /// protected void PopulateFromValue(TCollection col, List list, object parent) { if (list is null) throw new ArgumentNullException(nameof(list)); foreach (var it in list) col.Add(BaseConverter.FromValue(it, parent)); } /// /// Deserializes a in into a new /// owned by . /// /// the to convert to a /// the object that will own the resulting /// a new holding the deserialized content of /// public override TCollection FromValue(Value? value, object parent) { if (value is not List list) throw new ArgumentException("Argument not a List", nameof(value)); var col = Create(list.Count, parent); PopulateFromValue(col, list, parent); return col; } /// /// Serializes a into a . /// /// the to serialize /// the object owning /// the that was serialized into /// public override Value? ToValue(TCollection? obj, object parent) => Value.From(obj.Select(t => BaseConverter.ToValue(t, parent))); } /// /// A which default constructs a converter for use as the value converter. /// /// the value type of the collection /// the type of the colleciton /// the type of the converter to use for /// public sealed class CollectionConverter : CollectionConverter where TCollection : ICollection where TConverter : ValueConverter, new() { /// /// Creates a using a default constructed /// element type. Equivalent to calling /// with a default-constructed . /// /// public CollectionConverter() : base(new TConverter()) { } } #if NET4 /// /// A for an , creating a when deserializing. /// /// the element type of the /// public class ISetConverter : CollectionConverter> { /// /// Creates an using the default converter for . /// /// public ISetConverter() : base() { } /// /// Creates an using the specified underlying converter for values. /// /// the underlying to use for the values public ISetConverter(ValueConverter underlying) : base(underlying) { } /// /// Creates a new (a ) for deserialization. /// /// the size to initialize it to /// the object that will own the new object /// the new protected override ISet Create(int size, object parent) => new HashSet(); } /// /// An which default constructs a converter for use as the value converter. /// /// the value type of the collection /// the type of the converter to use for /// public sealed class ISetConverter : ISetConverter where TConverter : ValueConverter, new() { /// /// Creates an using a default constructed /// element type. Equivalent to calling /// with a default-constructed . /// /// public ISetConverter() : base(new TConverter()) { } } #endif /// /// A for a . /// /// the element type of the /// public class ListConverter : CollectionConverter> { /// /// Creates an using the default converter for . /// /// public ListConverter() : base() { } /// /// Creates an using the specified underlying converter for values. /// /// the underlying to use for the values public ListConverter(ValueConverter underlying) : base(underlying) { } /// /// Creates a new for deserialization. /// /// the size to initialize it to /// the object that will own the new object /// the new protected override List Create(int size, object parent) => new(size); } /// /// A which default constructs a converter for use as the value converter. /// /// the value type of the collection /// the type of the converter to use for /// public sealed class ListConverter : ListConverter where TConverter : ValueConverter, new() { /// /// Creates an using a default constructed /// element type. Equivalent to calling /// with a default-constructed . /// /// public ListConverter() : base(new TConverter()) { } } /// /// A for an , creating a when deserializing. /// /// the element type of the /// public class IListConverter : CollectionConverter> { /// /// Creates an using the default converter for . /// /// public IListConverter() : base() { } /// /// Creates an using the specified underlying converter for values. /// /// the underlying to use for the values public IListConverter(ValueConverter underlying) : base(underlying) { } /// /// Creates a new (a ) for deserialization. /// /// the size to initialize it to /// the object that will own the new object /// the new protected override IList Create(int size, object parent) => new List(size); } /// /// An which default constructs a converter for use as the value converter. /// /// the value type of the collection /// the type of the converter to use for /// public sealed class IListConverter : IListConverter where TConverter : ValueConverter, new() { /// /// Creates an using a default constructed /// element type. Equivalent to calling /// with a default-constructed . /// /// public IListConverter() : base(new TConverter()) { } } }