// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
// This file is ported and adapted from ComputeSharp (Sergio0694/ComputeSharp),
// more info in ThirdPartyNotices.txt in the root of the project.
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
namespace CommunityToolkit.Mvvm.SourceGenerators.Extensions;
///
/// Extension methods for .
///
internal static class IncrementalValuesProviderExtensions
{
///
/// Groups items in a given sequence by a specified key.
///
/// The type of left items in each tuple.
/// The type of right items in each tuple.
/// The input instance.
/// A comparer.
/// An with the grouped results.
public static IncrementalValuesProvider<(TLeft Left, ImmutableArray Right)> GroupBy(
this IncrementalValuesProvider<(TLeft Left, TRight Right)> source,
IEqualityComparer comparer)
{
return source.Collect().SelectMany((item, _) =>
{
Dictionary.Builder> map = new(comparer);
foreach ((TLeft hierarchy, TRight info) in item)
{
if (!map.TryGetValue(hierarchy, out ImmutableArray.Builder builder))
{
builder = ImmutableArray.CreateBuilder();
map.Add(hierarchy, builder);
}
builder.Add(info);
}
ImmutableArray<(TLeft Hierarchy, ImmutableArray Properties)>.Builder result =
ImmutableArray.CreateBuilder<(TLeft, ImmutableArray)>();
foreach (KeyValuePair.Builder> entry in map)
{
result.Add((entry.Key, entry.Value.ToImmutable()));
}
return result;
});
}
///
/// Creates a new instance with a gven pair of comparers.
///
/// The type of left items in each tuple.
/// The type of right items in each tuple.
/// The input instance.
/// An instance for items.
/// An instance for items.
/// An with the specified comparers applied to each item.
public static IncrementalValuesProvider<(TLeft Left, TRight Right)> WithComparers(
this IncrementalValuesProvider<(TLeft Left, TRight Right)> source,
IEqualityComparer comparerLeft,
IEqualityComparer comparerRight)
{
return source.WithComparer(new Comparer(comparerLeft, comparerRight));
}
///
/// Creates a new instance with a gven pair of comparers.
///
/// The type of first items in each tuple.
/// The type of second items in each tuple.
/// The type of third items in each tuple.
/// The input instance.
/// An instance for items.
/// An instance for items.
/// An instance for items.
/// An with the specified comparers applied to each item.
public static IncrementalValuesProvider<(T1, T2, T3)> WithComparers(
this IncrementalValuesProvider<(T1, T2, T3)> source,
IEqualityComparer comparer1,
IEqualityComparer comparer2,
IEqualityComparer comparer3)
{
return source.WithComparer(new Comparer(comparer1, comparer2, comparer3));
}
///
/// An implementation for a value tuple.
///
private sealed class Comparer : IEqualityComparer<(TLeft Left, TRight Right)>
{
///
/// The comparer.
///
private readonly IEqualityComparer comparerLeft;
///
/// The comparer.
///
private readonly IEqualityComparer comparerRight;
///
/// Creates a new instance with the specified parameters.
///
/// The comparer.
/// The comparer.
public Comparer(IEqualityComparer comparerLeft, IEqualityComparer comparerRight)
{
this.comparerLeft = comparerLeft;
this.comparerRight = comparerRight;
}
///
public bool Equals((TLeft Left, TRight Right) x, (TLeft Left, TRight Right) y)
{
return
this.comparerLeft.Equals(x.Left, y.Left) &&
this.comparerRight.Equals(x.Right, y.Right);
}
///
public int GetHashCode((TLeft Left, TRight Right) obj)
{
return HashCode.Combine(
this.comparerLeft.GetHashCode(obj.Left),
this.comparerRight.GetHashCode(obj.Right));
}
}
///
/// An implementation for a value tuple.
///
private sealed class Comparer : IEqualityComparer<(T1, T2, T3)>
{
///
/// The comparer.
///
private readonly IEqualityComparer comparer1;
///
/// The comparer.
///
private readonly IEqualityComparer comparer2;
///
/// The comparer.
///
private readonly IEqualityComparer comparer3;
///
/// Creates a new instance with the specified parameters.
///
/// The comparer.
/// The comparer.
/// The comparer.
public Comparer(IEqualityComparer comparer1, IEqualityComparer comparer2, IEqualityComparer comparer3)
{
this.comparer1 = comparer1;
this.comparer2 = comparer2;
this.comparer3 = comparer3;
}
///
public bool Equals((T1, T2, T3) x, (T1, T2, T3) y)
{
return
this.comparer1.Equals(x.Item1, y.Item1) &&
this.comparer2.Equals(x.Item2, y.Item2) &&
this.comparer3.Equals(x.Item3, y.Item3);
}
///
public int GetHashCode((T1, T2, T3) obj)
{
return HashCode.Combine(
this.comparer1.GetHashCode(obj.Item1),
this.comparer2.GetHashCode(obj.Item2),
this.comparer3.GetHashCode(obj.Item3));
}
}
}