// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// Taken from https://github.com/CommunityToolkit/dotnet/blob/ecd1711b740f4f88d2bb943ce292ae4fc90df1bc/src/CommunityToolkit.Mvvm.SourceGenerators/Helpers/EquatableArray%7BT%7D.cs
using System.Collections;
using System.Collections.Immutable;
using System.Diagnostics.CodeAnalysis;
using System.Runtime.CompilerServices;
namespace Robust.Roslyn.Shared.Helpers;
#nullable enable
///
/// Extensions for .
///
public static class EquatableArray
{
///
/// Creates an instance from a given .
///
/// The type of items in the input array.
/// The input instance.
/// An instance from a given .
public static EquatableArray AsEquatableArray(this ImmutableArray array)
where T : IEquatable
{
return new(array);
}
}
///
/// An immutable, equatable array. This is equivalent to but with value equality support.
///
/// The type of values in the array.
public readonly struct EquatableArray : IEquatable>, IEnumerable
where T : IEquatable
{
///
/// The underlying array.
///
private readonly T[]? array;
///
/// Creates a new instance.
///
/// The input to wrap.
public EquatableArray(ImmutableArray array)
{
this.array = Unsafe.As, T[]?>(ref array);
}
///
/// Gets a reference to an item at a specified position within the array.
///
/// The index of the item to retrieve a reference to.
/// A reference to an item at a specified position within the array.
public ref readonly T this[int index]
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => ref AsImmutableArray().ItemRef(index);
}
///
/// Gets a value indicating whether the current array is empty.
///
public bool IsEmpty
{
[MethodImpl(MethodImplOptions.AggressiveInlining)]
get => AsImmutableArray().IsEmpty;
}
///
public bool Equals(EquatableArray array)
{
return AsSpan().SequenceEqual(array.AsSpan());
}
///
public override bool Equals([NotNullWhen(true)] object? obj)
{
return obj is EquatableArray array && Equals(this, array);
}
///
public override int GetHashCode()
{
if (this.array is not T[] array)
{
return 0;
}
HashCode hashCode = default;
foreach (T item in array)
{
hashCode.Add(item);
}
return hashCode.ToHashCode();
}
///
/// Gets an instance from the current .
///
/// The from the current .
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public ImmutableArray AsImmutableArray()
{
return Unsafe.As>(ref Unsafe.AsRef(in this.array));
}
///
/// Creates an instance from a given .
///
/// The input instance.
/// An instance from a given .
public static EquatableArray FromImmutableArray(ImmutableArray array)
{
return new(array);
}
///
/// Returns a wrapping the current items.
///
/// A wrapping the current items.
public ReadOnlySpan AsSpan()
{
return AsImmutableArray().AsSpan();
}
///
/// Copies the contents of this instance to a mutable array.
///
/// The newly instantiated array.
public T[] ToArray()
{
return AsImmutableArray().ToArray();
}
///
/// Gets an value to traverse items in the current array.
///
/// An value to traverse items in the current array.
public ImmutableArray.Enumerator GetEnumerator()
{
return AsImmutableArray().GetEnumerator();
}
///
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)AsImmutableArray()).GetEnumerator();
}
///
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)AsImmutableArray()).GetEnumerator();
}
///
/// Implicitly converts an to .
///
/// An instance from a given .
public static implicit operator EquatableArray(ImmutableArray array)
{
return FromImmutableArray(array);
}
///
/// Implicitly converts an to .
///
/// An instance from a given .
public static implicit operator ImmutableArray(EquatableArray array)
{
return array.AsImmutableArray();
}
///
/// Checks whether two values are the same.
///
/// The first value.
/// The second value.
/// Whether and are equal.
public static bool operator ==(EquatableArray left, EquatableArray right)
{
return left.Equals(right);
}
///
/// Checks whether two values are not the same.
///
/// The first value.
/// The second value.
/// Whether and are not equal.
public static bool operator !=(EquatableArray left, EquatableArray right)
{
return !left.Equals(right);
}
}