Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fixed memory leak caused by query variables (#5383) #5569

Closed
wants to merge 5 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
106 changes: 0 additions & 106 deletions src/StrawberryShake/Client/src/Core/Helper/ComparisonHelper.cs

This file was deleted.

191 changes: 191 additions & 0 deletions src/StrawberryShake/Client/src/Core/Internal/ComparisonHelper.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,191 @@
using System.Collections;
using System.Collections.Generic;
using System.Linq;

namespace StrawberryShake.Internal;

public static class ComparisonHelper
{
public static bool SequenceEqual<TSource>(
IEnumerable<TSource>? first,
IEnumerable<TSource>? second)
{
if (ReferenceEquals(first, second))
{
return true;
}

if (ReferenceEquals(first, null) || ReferenceEquals(second, null))
{
return false;
}

return first.SequenceEqual(second);
}

public static bool SequenceEqual<TSource>(
IEnumerable<IEnumerable<TSource>?>? first,
IEnumerable<IEnumerable<TSource>?>? second)
{
if (ReferenceEquals(first, second))
{
return true;
}

if (ReferenceEquals(first, null) || ReferenceEquals(second, null))
{
return false;
}

using var e1 = first.GetEnumerator();
using var e2 = second.GetEnumerator();

while (e1.MoveNext())
{
if (!(e2.MoveNext() && SequenceEqual(e1.Current, e2.Current)))
{
return false;
}
}

return !e2.MoveNext();
}

public static bool SequenceEqual(IEnumerable? first, IEnumerable? second)
{
if (ReferenceEquals(first, second))
{
return true;
}

if (ReferenceEquals(first, null) || ReferenceEquals(second, null))
{
return false;
}

var e1 = first.GetEnumerator();
var e2 = second.GetEnumerator();

while (e1.MoveNext())
{
if (!e2.MoveNext())
{
return false;
}

if (!ObjEqual(e1.Current, e2.Current))
{
return false;
}
}

return !e2.MoveNext();
}

public static bool DictionaryEqual(
IReadOnlyDictionary<string, object?>? first,
IReadOnlyDictionary<string, object?>? second)
{
if (ReferenceEquals(first, second))
{
return true;
}

if (ReferenceEquals(first, null) || ReferenceEquals(second, null))
{
return false;
}

return DictionaryEqualInternal(second, first);
}

private static bool DictionaryEqualInternal<T>(T first, T second)
where T : IReadOnlyDictionary<string, object?>
{
if (first.Count != second.Count)
{
return false;
}

foreach (var firstItem in first)
{
if (!second.TryGetValue(firstItem.Key, out var secondValue))
{
return false;
}

if (!ObjEqual(firstItem.Value, secondValue))
{
return false;
}
}

return true;
}

private static bool ListEqualInternal<T>(T first, T second)
where T : IReadOnlyList<object?>
{
if (first.Count != second.Count)
{
return false;
}

for (var i = 0; i < first.Count; i++)
{
if (!ObjEqual(first[i], second[i]))
{
return false;
}
}

return true;
}

private static bool ObjEqual(object? first, object? second)
{
if (ReferenceEquals(first, second))
{
return true;
}

if (ReferenceEquals(first, null) || ReferenceEquals(second, null))
{
return false;
}

if (first is Dictionary<string, object?> firstDict &&
second is Dictionary<string, object?> secondDict)
{
return DictionaryEqualInternal(firstDict, secondDict);
}

if (first is List<object?> firstList &&
second is List<object?> secondList)
{
return ListEqualInternal(firstList, secondList);
}

if (first is IReadOnlyDictionary<string, object?> firstReadDict &&
second is IReadOnlyDictionary<string, object?> secondReadDict)
{
return DictionaryEqualInternal(firstReadDict, secondReadDict);
}

if (first is IEnumerable<KeyValuePair<string, object?>> firstKvp &&
second is IEnumerable<KeyValuePair<string, object?>> secondKvp)
{
return DictionaryEqualInternal(firstKvp.ToDictionary(x => x.Key, x => x.Value), secondKvp.ToDictionary(x => x.Key, x => x.Value));
}

if (first is not string &&
second is not string &&
first is IEnumerable firstEnum &&
second is IEnumerable secondEnum)
{
return SequenceEqual(firstEnum, secondEnum);
}

return Equals(first, second);
}
}
Loading