File: Comparers\OpenApiAnyComparer.cs
Web Access
Project: src\src\OpenApi\src\Microsoft.AspNetCore.OpenApi.csproj (Microsoft.AspNetCore.OpenApi)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Linq;
using Microsoft.OpenApi.Any;
using Microsoft.OpenApi.Interfaces;
 
namespace Microsoft.AspNetCore.OpenApi;
 
internal sealed class OpenApiAnyComparer : IEqualityComparer<IOpenApiAny>, IEqualityComparer<IOpenApiExtension>
{
    public static OpenApiAnyComparer Instance { get; } = new OpenApiAnyComparer();
 
    public bool Equals(IOpenApiAny? x, IOpenApiAny? y)
    {
        if (x is null && y is null)
        {
            return true;
        }
        if (x is null || y is null)
        {
            return false;
        }
        if (object.ReferenceEquals(x, y))
        {
            return true;
        }
 
        return x.AnyType == y.AnyType &&
            (x switch
            {
                OpenApiNull _ => y is OpenApiNull,
                OpenApiArray arrayX => y is OpenApiArray arrayY && ComparerHelpers.ListEquals(arrayX, arrayY, Instance),
                OpenApiObject objectX => y is OpenApiObject objectY && ComparerHelpers.DictionaryEquals(objectX, objectY, Instance),
                OpenApiBinary binaryX => y is OpenApiBinary binaryY && binaryX.Value.SequenceEqual(binaryY.Value),
                OpenApiInteger integerX => y is OpenApiInteger integerY && integerX.Value == integerY.Value,
                OpenApiLong longX => y is OpenApiLong longY && longX.Value == longY.Value,
                OpenApiDouble doubleX => y is OpenApiDouble doubleY && doubleX.Value == doubleY.Value,
                OpenApiFloat floatX => y is OpenApiFloat floatY && floatX.Value == floatY.Value,
                OpenApiBoolean booleanX => y is OpenApiBoolean booleanY && booleanX.Value == booleanY.Value,
                OpenApiString stringX => y is OpenApiString stringY && stringX.Value == stringY.Value,
                OpenApiPassword passwordX => y is OpenApiPassword passwordY && passwordX.Value == passwordY.Value,
                OpenApiByte byteX => y is OpenApiByte byteY && byteX.Value.SequenceEqual(byteY.Value),
                OpenApiDate dateX => y is OpenApiDate dateY && dateX.Value == dateY.Value,
                OpenApiDateTime dateTimeX => y is OpenApiDateTime dateTimeY && dateTimeX.Value == dateTimeY.Value,
                _ => x.Equals(y)
            });
    }
 
    public int GetHashCode(IOpenApiAny obj)
    {
        var hashCode = new HashCode();
        hashCode.Add(obj.AnyType);
        if (obj is IOpenApiPrimitive primitive)
        {
            hashCode.Add(primitive.PrimitiveType);
        }
        if (obj is OpenApiBinary binary)
        {
            hashCode.AddBytes(binary.Value);
        }
        if (obj is OpenApiByte bytes)
        {
            hashCode.AddBytes(bytes.Value);
        }
        hashCode.Add<object?>(obj switch
        {
            OpenApiInteger integer => integer.Value,
            OpenApiLong @long => @long.Value,
            OpenApiDouble @double => @double.Value,
            OpenApiFloat @float => @float.Value,
            OpenApiBoolean boolean => boolean.Value,
            OpenApiString @string => @string.Value,
            OpenApiPassword password => password.Value,
            OpenApiDate date => date.Value,
            OpenApiDateTime dateTime => dateTime.Value,
            _ => null
        });
 
        return hashCode.ToHashCode();
    }
 
    public bool Equals(IOpenApiExtension? x, IOpenApiExtension? y)
    {
        if (x is null && y is null)
        {
            return true;
        }
 
        if (x is null || y is null)
        {
            return false;
        }
 
        if (object.ReferenceEquals(x, y))
        {
            return true;
        }
 
        if (x is IOpenApiAny openApiAnyX && y is IOpenApiAny openApiAnyY)
        {
            return Equals(openApiAnyX, openApiAnyY);
        }
 
        return x.Equals(y);
    }
 
    public int GetHashCode(IOpenApiExtension obj)
    {
        if (obj is IOpenApiAny any)
        {
            return GetHashCode(any);
        }
 
        return obj.GetHashCode();
    }
}