<PackageReference Include="NUnit" Version="4.4.0" />

StreamsComparer

static class StreamsComparer
Comparator for two Streams.
using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Runtime.CompilerServices; namespace NUnit.Framework.Constraints.Comparers { [System.Runtime.CompilerServices.NullableContext(1)] [System.Runtime.CompilerServices.Nullable(0)] internal static class StreamsComparer { [System.Runtime.CompilerServices.Nullable(0)] internal static class LocalPool { [System.Runtime.CompilerServices.Nullable(0)] private sealed class Buffer { public static int Where { get; set; } public byte[] Data { get; } = new byte[4096]; public bool Rented { get; set; } public byte[] Rent() { Rented = true; return Data; } public void Return() { Rented = false; } } private static readonly List<Buffer> Buffers = new List<Buffer>(2) { new Buffer(), new Buffer() }; internal static int RentedBuffers => Buffers.Count((Buffer b) => b.Rented); internal static int AvailableBuffers => Buffers.Count((Buffer b) => !b.Rented); public static byte[] Rent() { lock (Buffers) { Buffer buffer = Buffers.Find((Buffer b) => !b.Rented); if (buffer == null) { buffer = new Buffer(); Buffers.Add(buffer); } return buffer.Rent(); } } public static void Return(byte[] data) { lock (Buffers) { Buffer buffer = Buffers.Find((Buffer b) => data == b.Data); if (buffer == null) throw new ArgumentException("Buffer not found in pool", "data"); if (!buffer.Rented) throw new ArgumentException("Buffer not rented out", "data"); buffer.Return(); } } } private const int BUFFER_SIZE = 4096; public static EqualMethodResult Equal(object x, object y, ref Tolerance tolerance, ComparisonState state, NUnitEqualityComparer equalityComparer) { Stream stream = x as Stream; if (stream != null) { Stream stream2 = y as Stream; if (stream2 != null) { if (tolerance.HasVariance) return EqualMethodResult.ToleranceNotSupported; if (stream == stream2) return EqualMethodResult.ComparedEqual; if (!stream.CanRead) throw new ArgumentException("Stream is not readable", "expected"); if (!stream2.CanRead) throw new ArgumentException("Stream is not readable", "actual"); bool flag = stream.CanSeek && stream2.CanSeek; if (flag) { if (stream.Length != stream2.Length) return EqualMethodResult.ComparedNotEqual; if (stream.Length == 0) return EqualMethodResult.ComparedEqual; } BinaryReader binaryReader = new BinaryReader(stream); BinaryReader binaryReader2 = new BinaryReader(stream2); long position = flag ? stream.Position : 0; long position2 = flag ? stream2.Position : 0; byte[] array = null; byte[] array2 = null; try { array = LocalPool.Rent(); array2 = LocalPool.Rent(); if (stream.CanSeek) binaryReader.BaseStream.Seek(0, SeekOrigin.Begin); if (stream2.CanSeek) binaryReader2.BaseStream.Seek(0, SeekOrigin.Begin); int num = 1; int num2 = 1; long num3 = 0; while (num > 0 && num2 > 0) { num = binaryReader.Read(array, 0, 4096); num2 = binaryReader2.Read(array2, 0, 4096); if (((ReadOnlySpan<byte>)array).SequenceEqual((ReadOnlySpan<byte>)array2)) num3 += num2; else { for (int i = 0; i < 4096; i++) { if (array[i] != array2[i]) { NUnitEqualityComparer.FailurePoint failurePoint = new NUnitEqualityComparer.FailurePoint(); failurePoint.Position = num3 + i; failurePoint.ExpectedHasData = true; failurePoint.ExpectedValue = array[i]; failurePoint.ActualHasData = true; failurePoint.ActualValue = array2[i]; equalityComparer.FailurePoints.Insert(0, failurePoint); return EqualMethodResult.ComparedNotEqual; } } } } } finally { if (stream.CanSeek) stream.Position = position; if (stream2.CanSeek) stream2.Position = position2; if (array != null) LocalPool.Return(array); if (array2 != null) LocalPool.Return(array2); } return EqualMethodResult.ComparedEqual; } } return EqualMethodResult.TypesNotSupported; } } }