using System.Collections; using System.Collections.Immutable; using System.Numerics; namespace Just.Core.Collections; public class ImmutableSequence : IEnumerable, IReadOnlyList, IEquatable>, IEqualityOperators, ImmutableSequence, bool> { private static readonly int InitialHash = typeof(ImmutableSequence).GetHashCode(); private static readonly Func CompareItem = EqualityComparer.Default.Equals; private readonly ImmutableList _values; public ImmutableSequence(ImmutableList values) => _values = values; public ImmutableSequence() : this(ImmutableArray.Empty) { } public ImmutableSequence(IEnumerable values) { _values = [..values]; } public ImmutableSequence(ReadOnlySpan values) : this(ImmutableList.Create(values)) { } public bool IsEmpty => _values.IsEmpty; public int Count => _values.Count; public T this[int index] => _values[index]; public T this[Index index] => _values[index]; public ImmutableSequence this[Range range] { get { var (offset, count) = range.GetOffsetAndLength(_values.Count); return ConstructNew(_values.GetRange(offset, count)); } } protected virtual ImmutableSequence ConstructNew(ImmutableList values) => new(values); public ImmutableSequence Add(T value) => ConstructNew([.._values, value]); public ImmutableSequence AddFront(T value) => ConstructNew([value, .._values]); public ImmutableList.Enumerator GetEnumerator() => _values.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_values).GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)_values).GetEnumerator(); public override string ToString() => string.Join(Environment.NewLine, _values); public virtual bool Equals([NotNullWhen(true)] ImmutableSequence? other) { if (ReferenceEquals(this, other)) { return true; } if (_values.Count != other?._values.Count) { return false; } for (int i = 0; i < _values.Count; i++) { if (!CompareItem(_values[i], other._values[i])) { return false; } } return true; } public override bool Equals([NotNullWhen(true)] object? obj) => Equals(obj as ImmutableSequence); public override int GetHashCode() { HashCode hash = new(); hash.Add(InitialHash); foreach (var value in _values) { hash.Add(value); } return hash.ToHashCode(); } public static bool operator ==(ImmutableSequence? left, ImmutableSequence? right) => left is null ? right is null : left.Equals(right); public static bool operator !=(ImmutableSequence? left, ImmutableSequence? right) => !(left == right); }