// Copyright (c) Microsoft. All rights reserved.
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
namespace Microsoft.Agents.AI.Workflows.Generators.Models;
///
/// Provides an immutable list implementation which implements sequence equality.
/// Copied from: https://github.com/dotnet/runtime/blob/main/src/libraries/Common/src/SourceGenerators/ImmutableEquatableArray.cs
///
internal sealed class ImmutableEquatableArray : IEquatable>, IReadOnlyList
where T : IEquatable
{
///
/// Creates a new empty .
///
public static ImmutableEquatableArray Empty { get; } = new ImmutableEquatableArray(Array.Empty());
private readonly T[] _values;
///
/// Gets the element at the specified index.
///
///
///
public T this[int index] => this._values[index];
///
/// Gets the number of elements contained in the collection.
///
public int Count => this._values.Length;
///
/// Gets whether the array is empty.
///
public bool IsEmpty => this._values.Length == 0;
///
/// Initializes a new instance of the ImmutableEquatableArray{T} class that contains the elements from the specified
/// collection.
///
/// The elements from the provided collection are copied into the immutable array. Subsequent
/// changes to the original collection do not affect the contents of this array.
/// The collection of elements to initialize the array with. Cannot be null.
public ImmutableEquatableArray(IEnumerable values) => this._values = values.ToArray();
///
public bool Equals(ImmutableEquatableArray? other) => other != null && ((ReadOnlySpan)this._values).SequenceEqual(other._values);
///
public override bool Equals(object? obj)
=> obj is ImmutableEquatableArray other && this.Equals(other);
///
public override int GetHashCode()
{
int hash = 0;
foreach (T value in this._values)
{
hash = HashHelpers.Combine(hash, value is null ? 0 : value.GetHashCode());
}
return hash;
}
///
public Enumerator GetEnumerator() => new(this._values);
IEnumerator IEnumerable.GetEnumerator() => ((IEnumerable)this._values).GetEnumerator();
IEnumerator IEnumerable.GetEnumerator() => this._values.GetEnumerator();
///
public struct Enumerator
{
private readonly T[] _values;
private int _index;
internal Enumerator(T[] values)
{
this._values = values;
this._index = -1;
}
///
public bool MoveNext()
{
int newIndex = this._index + 1;
if ((uint)newIndex < (uint)this._values.Length)
{
this._index = newIndex;
return true;
}
return false;
}
///
/// The element at the current position of the enumerator.
///
public readonly T Current => this._values[this._index];
}
}
internal static class ImmutableEquatableArray
{
public static ImmutableEquatableArray ToImmutableEquatableArray(this IEnumerable values) where T : IEquatable
=> new(values);
}
// Copied from https://github.com/dotnet/runtime/blob/main/src/libraries/System.Private.CoreLib/src/System/Numerics/Hashing/HashHelpers.cs#L6
internal static class HashHelpers
{
public static int Combine(int h1, int h2)
{
// RyuJIT optimizes this to use the ROL instruction
// Related GitHub pull request: https://github.com/dotnet/coreclr/pull/1830
uint rol5 = ((uint)h1 << 5) | ((uint)h1 >> 27);
return ((int)rol5 + h1) ^ h2;
}
}