diff --git a/Recyclable.Collections.Compatibility.List.Tests/RecyclableLongListCompatibilityListTests.cs b/Recyclable.Collections.Compatibility.List.Tests/RecyclableLongListCompatibilityListTests.cs new file mode 100644 index 0000000..0f49f12 --- /dev/null +++ b/Recyclable.Collections.Compatibility.List.Tests/RecyclableLongListCompatibilityListTests.cs @@ -0,0 +1,1129 @@ +using FluentAssertions; +using Recyclable.Collections; +using Recyclable.Collections.TestData; +using Recyclable.Collections.Pools; +using System.Numerics; +using System.Collections; + +#pragma warning disable xUnit1026, RCS1163, IDE0039, IDE0060, RCS1235 + +namespace Recyclable.CollectionsTests +{ + public class RecyclableLongListCompatibilityListTests + { + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void BinarySearchShouldFindAllItems(string testCase, IEnumerable testData, int itemsCount, int minBlockSize, in long[] itemIndexes) + { + _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); + + // Prepare + using var list = new RecyclableLongList(testData, minBlockSize, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expectedItem = expectedData[(int)itemIndex]; + var expected = expectedData.BinarySearch(expectedItem); + + // Act + var actual = list.BinarySearch(expectedItem); + + // Validate + _ = actual.Should().Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void ConvertAllShouldConvertAllItems(string testCase, IEnumerable testData, int minBlockSize, int itemsCount) + { + // Prepare + using var list = new RecyclableLongList(testData, minBlockSize, initialCapacity: itemsCount); + var expectedData = testData.ToList().ConvertAll(item => item + 0.1); + + // Act + using var actual = list.ConvertAll(item => item + 0.1); + + // Validate + _ = actual.Count.Should().Be(itemsCount); + _ = actual.Should().Equal(expectedData); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeVariants), MemberType = typeof(RecyclableLongListTestData))] + public void CopyToShouldCopyAllItemsInTheCorrectOrderWhenFromStart(string testCase, IEnumerable testData, int itemsCount, int minBlockSize) + { + // Prepare + using var list = new RecyclableLongList(testData, minBlockSize, initialCapacity: itemsCount); + long[] copiedItems = new long[itemsCount]; + + // Act + list.CopyTo(copiedItems); + + // Validate + long[] expectedData = new long[itemsCount]; + testData.ToList().CopyTo(expectedData); + + _ = copiedItems.Should().Equal(testData); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithBlockSizeWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void ExistsShouldFindAllItems(string testCase, IEnumerable testData, int itemsCount, int minBlockSize, in long[] itemIndexes) + { + _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); + + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expectedItem = expectedData[(int)itemIndex]; + var expected = expectedData.Exists(item => item == expectedItem); + + // Act + var actual = list.Exists(item => item == expectedItem); + + // Validate + _ = actual.Should().Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void ExistsShouldNotFindNonExistingItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); + + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expectedItem = expectedData[(int)itemIndex]; + var expected = expectedData.Exists(item => item == -expectedItem); + + // Act + var actual = list.Exists(item => item == -expectedItem); + + // Validate + _ = actual.Should().Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindAllIndexesShouldReturnCorrectIndexes(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + //* There is no equivalent of .FindAllIndexes in List, so no comparison here. + + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + + foreach (var itemIndex in itemIndexes) + { + // Act + using var actual = list.FindAllIndexes(item => item == itemIndex + 1); + + // Validate + _ = actual.Count.Should().Be(1); + if (itemsCount > 0) + { + _ = actual.Count.Should().Be(1); + _ = actual.Should().AllSatisfy(x => x.Should().Be((int)itemIndex)); + } + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.ItemsCountTestCases), MemberType = typeof(RecyclableLongListTestData))] + public void FindAllShouldReturnCorrectIndexes(int itemsCount) + { + const int ExpectedItem = 1; + + // Prepare + var testData = Enumerable.Range(0, itemsCount).Select(value => value % 2 == 0 ? ExpectedItem : -ExpectedItem); + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + + // Act + using var actual = list.FindAll(x => x == ExpectedItem); + + // Validate + var expectedData = testData.ToList().FindAll(x => x == ExpectedItem); + + _ = actual.Count.Should().Be(expectedData.Count); + _ = actual.Should().Equal(expectedData); + if (expectedData.Count > 0) + { + _ = actual.Should().AllSatisfy(x => x.Should().Be(ExpectedItem)).And.Equal(expectedData); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.ItemsCountTestCases), MemberType = typeof(RecyclableLongListTestData))] + public void FindAllShouldNotFindNonExistingItems(int itemsCount) + { + const int ExpectedItem = 1; + + // Prepare + var testData = Enumerable.Range(0, itemsCount).Select(_ => ExpectedItem); + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + + // Act + using var foundItems = list.FindAll(x => x == -ExpectedItem); + + // Validate + var expectedData = testData.ToList().FindAll(x => x == -ExpectedItem); + + _ = foundItems.Count.Should().Be(expectedData.Count); + _ = foundItems.Should().Equal(expectedData); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindIndexShouldReturnCorrectIndexes(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expectedItem = expectedData[(int)itemIndex]; + + // Act + var actual = list.FindIndex(item => item == expectedItem); + + // Validate + var expected = expectedData.FindIndex(item => item == expectedItem); + + _ = actual.Should().Be((int)itemIndex).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindIndexShouldReturnCorrectIndexesWhenConstrainedCount(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expectedItem = expectedData[(int)itemIndex]; + var expected = expectedData.FindIndex((int)itemIndex, (int)(itemsCount - itemIndex), item => item == expectedItem); + + // Act + var actual = list.FindIndex((int)itemIndex, (int)(itemsCount - itemIndex), item => item == expectedItem); + + // Validate + _ = actual.Should().Be((int)itemIndex).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindIndexShouldNotAnythingWhenRangeExcludesItem(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expectedItem = expectedData[(int)itemIndex]; + var expected = expectedData.FindIndex((int)itemIndex + 1, (int)(itemsCount - itemIndex - 1), item => item == expectedItem); + + // Act + var actual = list.FindIndex((int)itemIndex + 1, (int)(itemsCount - itemIndex - 1), item => item == expectedItem); + + // Validate + _ = actual.Should().Be(-1).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindIndexShouldReturnCorrectIndexesWhenConstrainedIndex(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expectedItem = expectedData[(int)itemIndex]; + var expected = expectedData.FindIndex(Math.Min(1, (int)itemIndex), item => item == expectedItem); + + // Act + var actual = list.FindIndex(Math.Min(1, (int)itemIndex), item => item == expectedItem); + + // Validate + _ = actual.Should().Be((int)itemIndex).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindLastIndexShouldReturnCorrectIndexes(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expectedItem = expectedData[(int)itemIndex]; + var expected = expectedData.FindLastIndex(x => x == expectedItem); + + // Act + var actual = list.FindLastIndex(x => x == expectedItem); + + // Validate + _ = actual.Should().Be((int)itemIndex).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindLastIndexShouldReturnCorrectIndexesWhenConstrainedCount(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expectedItem = expectedData[(int)itemIndex]; + + // Act & Validate + var expected = expectedData.FindLastIndex(itemsCount - 1, itemsCount, x => x == expectedItem); + _ = list.FindLastIndex(itemsCount - 1, itemsCount, x => x == expectedItem).Should().Be((int)itemIndex).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindLastIndexShouldReturnCorrectIndexesWhenConstrainedIndex(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expectedItem = expectedData[(int)itemIndex]; + var expected = expectedData.FindLastIndex(itemsCount - 1, x => x == expectedItem); + + // Act + var actual = list.FindLastIndex(itemsCount - 1, x => x == expectedItem); + + // Validate + _ = actual.Should().Be((int)itemIndex).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindLastIndexShouldThrowArgumentOutOfRange(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expectedItem = expectedData[(int)itemIndex]; + int expected = int.MinValue; + + // Act & Validate + if (itemsCount - 1 != -1) + { + Assert.Throws(() => expected = expectedData.FindLastIndex(itemsCount - 1, itemsCount + 3, x => x == expectedItem)); + Assert.Throws(() => _ = list.FindLastIndex(itemsCount - 1, itemsCount + 3, x => x == expectedItem).Should().Be((int)itemIndex).And.Be(expected)); + } + else + { + expected = expectedData.FindLastIndex(itemsCount - 1, itemsCount + 3, x => x == expectedItem); + _ = list.FindLastIndex(itemsCount - 1, itemsCount + 3, x => x == expectedItem).Should().Be((int)itemIndex).And.Be(expected); + } + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindLastShouldReturnCorrectItem(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expectedItem = expectedData[(int)itemIndex]; + var expected = expectedData.FindLast(item => item == expectedItem); + + // Act + var actual = list.FindLast(item => item == expectedItem); + + // Validate + _ = actual.Should().Be(expectedData[(int)itemIndex]).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindShouldFindAllItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); + + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + long expectedItem = expectedData[(int)itemIndex]; + var expected = expectedData.Find(item => item == expectedItem); + + // Act + var actual = list.Find(item => item == expectedData[(int)itemIndex]); + + // Validate + _ = actual.Should().Be(expectedData[(int)itemIndex]); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void FindShouldNotFindNonExistingItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); + + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expected = expectedData.Find(item => item == -expectedData[(int)itemIndex]); + + // Act + var actual = list.Find(item => item == -expectedData[(int)itemIndex]); + + // Validate + actual.Should().Be(0).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] + public void ForEachShouldGiveItemsInCorrectOrder(string testCase, IEnumerable testData, int itemsCount) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + var expected = new List(itemsCount); + expectedData.ForEach(expected.Add); + + // Act + var yieldedItems = new List(itemsCount); + list.ForEach(yieldedItems.Add); + + // Validate + _ = yieldedItems.Should().Equal(testData).And.Equal(expected); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.EmptySourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] + public void ForEachShouldDoNothingWhenEmptyList(string testCase, IEnumerable testData, int itemsCount) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + var expected = new List(itemsCount); + expectedData.ForEach(expected.Add); + + // Act + var yieldedItems = new List(itemsCount); + list.ForEach(item => yieldedItems.Add(item)); + + // Validate + _ = yieldedItems.Should().BeEmpty().And.Equal(expected); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void GetRangeShouldReturnCorrectItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); + + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + int startingIndex = (int)Math.Min(1, itemIndex); + var expectedRangeItems = expectedData.GetRange(startingIndex, (int)itemIndex); + + // Act + using var rangeItems = list.GetRange(startingIndex, (int)itemIndex); + + // Validate + _ = rangeItems.Count.Should().Be(expectedRangeItems.Count); + _ = rangeItems.Should().Equal(expectedRangeItems); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void IndexOfShouldReturnCorrectIndexesWhenConstrainedCount(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expected = expectedData.IndexOf(expectedData[(int)itemIndex], (int)itemIndex, (int)(itemsCount - itemIndex)); + + // Act + var actual = list.IndexOf(expectedData[(int)itemIndex], (int)itemIndex, (int)(itemsCount - itemIndex)); + + // Validate + _ = actual.Should().Be((int)itemIndex).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void IndexOfShouldReturnCorrectIndexesWhenConstrainedIndex(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expected = expectedData.IndexOf(expectedData[(int)itemIndex], (int)itemIndex); + + // Act + var actual = list.IndexOf(expectedData[(int)itemIndex], (int)itemIndex); + + // Validate + _ = actual.Should().Be((int)itemIndex).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void InsertRangeShouldAddItemsInTheRightPosition(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + var expectedData = testData.Reverse().ToArray(); + + foreach (var itemIndex in itemIndexes) + { + using var list = new RecyclableLongList(testData.Reverse(), initialCapacity: itemsCount); + var expected = expectedData.ToList(); + expected.InsertRange((int)itemIndex, testData); + + if (testCase.Contains("Array[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, (Array)testData); + } + else if (testCase.Contains("ICollection[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, (ICollection)testData); + } + else if (testCase.Contains("ICollection[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, (ICollection)testData); + } + else if (testCase.Contains("IEnumerable[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, (IEnumerable)testData); + } + else if (testCase.Contains("IReadOnlyList[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, (IReadOnlyList)testData); + } + else if (testCase.Contains("ReadOnlySpan[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, new ReadOnlySpan((long[])testData)); + } + else if (testCase.Contains("Span[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, new Span((long[])testData)); + } + else if (testData is long[] testDataArray) + { + list.InsertRange((int)itemIndex, testDataArray); + } + else if (testData is List testDataList) + { + list.InsertRange((int)itemIndex, testDataList); + } + else if (testData is RecyclableList testDataRecyclableList) + { + list.InsertRange((int)itemIndex, testDataRecyclableList); + } + else if (testData is RecyclableLongList testDataRecyclableLongList) + { + list.InsertRange((int)itemIndex, testDataRecyclableLongList); + } + else if (testData is IList testDataIList) + { + list.InsertRange((int)itemIndex, testDataIList); + } + else if (testData is IEnumerable testDataIEnumerable) + { + list.InsertRange((int)itemIndex, testDataIEnumerable); + } + else + { + throw new InvalidCastException("Unknown type of test data"); + } + + // Validate + list.Count.Should().Be(itemsCount << 1); + _ = list.Should().Equal(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void LastIndexOfShouldReturnCorrectIndexes(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expected = expectedData.LastIndexOf(expectedData[(int)itemIndex]); + + // Act + var actual = list.LastIndexOf(expectedData[(int)itemIndex]); + + // Validate + _ = actual.Should().Be((int)itemIndex).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void LastIndexOfShouldReturnCorrectIndexesWhenConstrainedCount(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expected = expectedData.LastIndexOf(expectedData[(int)itemIndex], itemsCount - 1, itemsCount); + + // Act + var actual = list.LastIndexOf(expectedData[(int)itemIndex], itemsCount - 1, itemsCount); + + // Validate + _ = actual.Should().Be((int)itemIndex).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void LastIndexOfShouldReturnCorrectIndexesWhenConstrainedIndex(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + var expected = expectedData.LastIndexOf(expectedData[(int)itemIndex], itemsCount - 1); + + // Act + var actual = list.LastIndexOf(expectedData[(int)itemIndex], itemsCount - 1); + + // Validate + _ = actual.Should().Be((int)itemIndex).And.Be(expected); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void LastIndexOfShouldThrowArgumentOutOfRangeWhenCountTooBig(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + + // Act & Validate + foreach (var itemIndex in itemIndexes) + { + _ = Assert.Throws(() => _ = expectedData.LastIndexOf(expectedData[(int)itemIndex], itemsCount - 1, itemsCount + 3).Should().Be((int)itemIndex)); + _ = Assert.Throws(() => _ = list.LastIndexOf(expectedData[(int)itemIndex], itemsCount - 1, itemsCount + 3).Should().Be((int)itemIndex)); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void InsertRangeShouldMoveItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + foreach (var itemIndex in itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData.Reverse(), initialCapacity: itemsCount); + var expectedItems = testData.Reverse().ToList(); + var item = expectedItems[^1]; + expectedItems.InsertRange((int)itemIndex, testData); + + // Act + if (testCase.Contains("Array[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, (Array)testData); + } + else if (testCase.Contains("ICollection[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, (ICollection)testData); + } + else if (testCase.Contains("ICollection[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, (ICollection)testData); + } + else if (testCase.Contains("IEnumerable[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, (IEnumerable)testData); + } + else if (testCase.Contains("IReadOnlyList[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, (IReadOnlyList)testData); + } + else if (testCase.Contains("ReadOnlySpan[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, new ReadOnlySpan((long[])testData)); + } + else if (testCase.Contains("Span[", StringComparison.OrdinalIgnoreCase)) + { + list.InsertRange((int)itemIndex, new Span((long[])testData)); + } + else if (testData is long[] testDataArray) + { + list.InsertRange((int)itemIndex, testDataArray); + } + else if (testData is List testDataList) + { + list.InsertRange((int)itemIndex, testDataList); + } + else if (testData is RecyclableList testDataRecyclableList) + { + list.InsertRange((int)itemIndex, testDataRecyclableList); + } + else if (testData is RecyclableLongList testDataRecyclableLongList) + { + list.InsertRange((int)itemIndex, testDataRecyclableLongList); + } + else if (testData is IList testDataIList) + { + list.InsertRange((int)itemIndex, testDataIList); + } + else if (testData is IEnumerable testDataIEnumerable) + { + list.InsertRange((int)itemIndex, testDataIEnumerable); + } + else + { + throw new InvalidCastException("Unknown type of test data"); + } + + // Validate + _ = list[(int)itemIndex].Should().Be(item); + _ = list.Count.Should().Be(itemsCount << 1); + _ = list.Capacity.Should().BeGreaterThanOrEqualTo(itemsCount << 1); + _ = list.Should().Equal(expectedItems); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void RemoveAllShouldRemoveTheCorrectItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var itemsToRemove = itemIndexes.Select(x => list[(int)x]).ToArray(); + var expectedItems = testData.ToList(); + var expectedResult = expectedItems.RemoveAll(itemsToRemove.Contains); + + // Act + var actualResult = list.RemoveAll(itemsToRemove.Contains); + + // Validate + _ = actualResult.Should().Be(expectedResult); + _ = list.Capacity.Should().BeGreaterThanOrEqualTo(itemsCount); + _ = list.Count.Should().Be(itemsCount - itemsToRemove.Length); + _ = list.Should().Equal(expectedItems); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void RemoveRangeShouldRemoveCorrectItems(string testCase, IEnumerable testData, int itemsCount, in long[] itemIndexes) + { + _ = testData.Any().Should().BeTrue("we need items on the list that we can look for"); + + foreach (var itemIndex in itemIndexes) + { + // Prepare + int startingIndex = (int)Math.Min(1, itemIndex); + var expectedData = testData.ToList(); + expectedData.RemoveRange(startingIndex, (int)itemIndex); + + // Act + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + list.RemoveRange(startingIndex, (int)itemIndex); + + // Validate + _ = list.Count.Should().Be(expectedData.Count); + _ = list.Should().Equal(expectedData); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] + public void ReverseShouldSwapItemsInCorrectOrder(string testCase, IEnumerable testData, int itemsCount) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedData = testData.ToList(); + expectedData.Reverse(); + + // Act + list.Reverse(); + + // Validate + _ = list.Should().Equal(expectedData); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void ReverseShouldSwapItemsInCorrectOrderWhenConstrained(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) + { + // Prepare + var expectedData = testData.ToArray(); + + foreach (var itemIndex in itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var startingItemIndex = (int)Math.Min(1, itemIndex); + var expectedRangeItems = expectedData.ToList(); + expectedRangeItems.Reverse(startingItemIndex, (int)itemIndex); + + // Act + list.Reverse(startingItemIndex, (int)itemIndex); + + // Validate + _ = list.Should().Equal(expectedRangeItems); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] + public void SortShouldSortItemsInCorrectOrder(string testCase, IEnumerable testData, int itemsCount) + { + // Prepare + using var list = new RecyclableLongList(testData.Reverse(), initialCapacity: itemsCount); + var expectedData = testData.Reverse().ToList(); + expectedData.Sort(); + + // Act + list.Sort(); + + // Validate + _ = list.Should().Equal(expectedData); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] + public void SortShouldSortItemsInCorrectOrderWhenWithComparer(string testCase, IEnumerable testData, int itemsCount) + { + // Prepare + using var list = new RecyclableLongList(testData.Reverse(), initialCapacity: itemsCount); + IComparer comparer = Comparer.Default; + var expectedData = testData.Reverse().ToList(); + expectedData.Sort(comparer); + + // Act + list.Sort(comparer); + + // Validate + _ = list.Should().Equal(expectedData); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] + public void SortShouldSortItemsInCorrectOrderWhenWithComparison(string testCase, IEnumerable testData, int itemsCount) + { + // Prepare + using var list = new RecyclableLongList(testData.Reverse(), initialCapacity: itemsCount); + + static int comparison(long x, long y) + { + return (x - y) switch + { + > 0 => 1, + < 0 => -1, + _ => 0, + }; + } + + var expectedData = testData.Reverse().ToList(); + expectedData.Sort(comparison); + + // Act + list.Sort(comparison); + + // Validate + _ = list.Should().Equal(expectedData); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void SortShouldSortItemsInCorrectOrderWhenConstrained(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) + { + // Prepare + IComparer comparer = Comparer.Default; + var expectedData = testData.Reverse().ToArray(); + + foreach (var itemIndex in itemIndexes) + { + // Prepare + using var list = new RecyclableLongList(testData.Reverse(), initialCapacity: itemsCount); + var startingIndex = (int)Math.Min(1, itemIndex); + + var expectedSortedData = expectedData.ToList(); + expectedSortedData.Sort(startingIndex, (int)itemIndex, comparer); + + // Act + list.Sort(startingIndex, (int)itemIndex, comparer); + + // Validate + _ = list.Should().Equal(expectedSortedData); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] + public void TrimExcessShouldDecreaseCapacity(string testCase, IEnumerable testData, int itemsCount) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedCapacity = itemsCount >= RecyclableDefaults.InitialCapacity ? itemsCount : RecyclableDefaults.InitialCapacity; + + // Act + list.TrimExcess(); + + // Validate + _ = list.Capacity.Should().Be(expectedCapacity); + _ = list.Count.Should().Be(itemsCount); + _ = list.Should().Equal(testData); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] + public void TrimExcessShouldNotBreakAdd(string testCase, IEnumerable testData, int itemsCount) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedCapacity = (int)BitOperations.RoundUpToPowerOf2((uint)itemsCount + 1); + expectedCapacity = expectedCapacity >= RecyclableDefaults.InitialCapacity ? expectedCapacity : RecyclableDefaults.InitialCapacity; + + // Act + list.TrimExcess(); + list.Add(-1); + + // Validate + _ = list.Capacity.Should().Be(expectedCapacity); + _ = list.Count.Should().Be(itemsCount + 1); + _ = list.Should().Equal(testData.Append(-1)); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] + public void TrimExcessShouldNotBreakAddRange(string testCase, IEnumerable testData, int itemsCount) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedCapacity = (int)BitOperations.RoundUpToPowerOf2(checked((uint)itemsCount << 1)); + expectedCapacity = expectedCapacity >= RecyclableDefaults.InitialCapacity ? expectedCapacity : RecyclableDefaults.InitialCapacity; + + // Act + list.TrimExcess(); + list.AddRange(testData); + + // Validate + _ = list.Capacity.Should().BeGreaterThanOrEqualTo(expectedCapacity); + _ = list.Count.Should().Be(itemsCount << 1); + _ = list.Should().Equal(testData.Concat(testData)); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] + public void TrimExcessShouldNotBreakClear(string testCase, IEnumerable testData, int itemsCount) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + + // Act + list.TrimExcess(); + list.Clear(); + + // Validate + _ = list.Capacity.Should().Be(Math.Max(RecyclableDefaults.InitialCapacity, itemsCount)); + _ = list.Count.Should().Be(0); + _ = list.Should().BeEmpty(); + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void TrimExcessShouldNotBreakInsert(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) + { + // Prepare + var expectedCapacity = (int)BitOperations.RoundUpToPowerOf2((uint)itemsCount + 1); + expectedCapacity = expectedCapacity >= RecyclableDefaults.InitialCapacity ? expectedCapacity : RecyclableDefaults.InitialCapacity; + var expectedData = testData.ToArray(); + + foreach (var itemIndex in itemIndexes) + { + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedItemsAfterInsert = expectedData.ToList(); + expectedItemsAfterInsert.Insert((int)itemIndex, -3); + + // Act + list.TrimExcess(); + list.Insert((int)itemIndex, -3); + + // Validate + _ = list.Capacity.Should().BeGreaterThanOrEqualTo(expectedCapacity); + _ = list.Count.Should().Be(expectedItemsAfterInsert.Count); + _ = list.Should().Equal(expectedItemsAfterInsert); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void TrimExcessShouldNotBreakRemove(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) + { + // Prepare + var expectedData = testData.ToArray(); + + foreach (var itemIndex in itemIndexes) + { + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + var expectedItemsAfterInsert = expectedData.ToList(); + expectedItemsAfterInsert.RemoveAt((int)itemIndex); + + // Act + list.TrimExcess(); + list.RemoveAt((int)itemIndex); + + // Validate + _ = list.Capacity.Should().BeGreaterThanOrEqualTo(itemsCount); + _ = list.Count.Should().Be(expectedItemsAfterInsert.Count); + _ = list.Should().Equal(expectedItemsAfterInsert); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void TrimExcessShouldNotBreakIndexOf(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) + { + // Prepare + var expectedData = testData.ToArray(); + + foreach (var itemIndex in itemIndexes) + { + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + + // Act + list.TrimExcess(); + var actual = list.IndexOf(expectedData[(int)itemIndex]); + + // Validate + _ = actual.Should().Be((int)itemIndex); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataVariants), MemberType = typeof(RecyclableLongListTestData))] + public void TrimmedArraysShouldNotBePooled(string testCase, IEnumerable testData, int itemsCount) + { + // Prepare + using var list = new RecyclableLongList(testData, initialCapacity: itemsCount); + + // Act + list.TrimExcess(); + var trimmedMemoryBlock = list.AsArray; + + list.Dispose(); + + // Validate + _ = list.Capacity.Should().Be(0); + _ = list.Count.Should().Be(0); + _ = list.Should().BeEmpty(); + + if (itemsCount >= RecyclableDefaults.MinPooledArrayLength) + { + var newMemoryBlock = RecyclableArrayPool.RentShared(itemsCount); + _ = BitOperations.IsPow2(itemsCount) + ? newMemoryBlock.Should().BeSameAs(trimmedMemoryBlock) + : newMemoryBlock.Should().NotBeSameAs(trimmedMemoryBlock); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void TrueForAllShouldBeFalseWhenNoMatch(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) + { + // Prepare + var expectedData = testData.ToList(); + + foreach (var itemIndex in itemIndexes) + { + using RecyclableList list = new(testData, initialCapacity: itemsCount); + Predicate condition = item => item == itemIndex; + var expected = expectedData.TrueForAll(condition); + + // Act + var actual = list.TrueForAll(condition); + + // Validate + _ = actual.Should().Be(expected).And.BeFalse(); + } + } + + [Theory] + [MemberData(nameof(RecyclableLongListTestData.SourceDataWithItemIndexVariants), MemberType = typeof(RecyclableLongListTestData))] + public void TrueForAllShouldBeTrueWhenMatched(string testCase, IEnumerable testData, int itemsCount, long[] itemIndexes) + { + // Prepare + using RecyclableList list = new(testData, initialCapacity: itemsCount); + int index = 0; + Predicate condition = item => item == ++index; + var expected = testData.ToList().TrueForAll(condition); + + index = 0; + + // Act + var actual = list.TrueForAll(condition); + + // Validate + _ = actual.Should().Be(expected).And.BeTrue(); + } + } +} \ No newline at end of file diff --git a/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.Find.cs b/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.Find.cs new file mode 100644 index 0000000..4a39a9a --- /dev/null +++ b/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.Find.cs @@ -0,0 +1,296 @@ +// Ignore Spelling: zzz + +using System.Numerics; + +namespace Recyclable.Collections +{ +#pragma warning disable IDE1006 // This intentional so that it shows at the end of IntelliSense list + public static class zzzRecyclableLongListCompatibilityListFind +#pragma warning restore IDE1006 // Naming Styles + { + public static bool Exists(this RecyclableLongList list, Predicate match) + { + //int sourceItemsCount = list._count; + //if (sourceItemsCount == 0) + //{ + // return false; + //} + + //ReadOnlySpan sourceSpan = list._memoryBlock; + //for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) + //{ + // if (match(sourceSpan[itemIndex])) + // { + // return true; + // } + //} + + //return false; + + throw new NotImplementedException(); + } + + public static T? Find(this RecyclableLongList list, Predicate match) + { + //int sourceItemsCount = list._count; + //if (sourceItemsCount == 0) + //{ + // return default; + //} + + //ReadOnlySpan sourceSpan = list._memoryBlock; + //for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) + //{ + // if (match(sourceSpan[itemIndex])) + // { + // return sourceSpan[itemIndex]; + // } + //} + + //return default; + + throw new NotImplementedException(); + } + + public static RecyclableList FindAll(this RecyclableLongList list, Predicate match) + { + //int sourceItemsCount = list._count; + //if (sourceItemsCount == 0) + //{ + // return new(); + //} + + //ReadOnlySpan sourceSpan = list._memoryBlock; + //RecyclableList result = new(sourceItemsCount >> 3); + //Span resultSpan = result._memoryBlock; + //int capacity = result._capacity, + // resultItemsCount = 0; + + //for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) + //{ + // if (match(sourceSpan[itemIndex])) + // { + // if (resultItemsCount + 1 > capacity) + // { + // capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)resultItemsCount + 1)); + // _ = RecyclableListHelpers.EnsureCapacity(result, resultItemsCount, capacity); + // resultSpan = result._memoryBlock; + // } + + // resultSpan[resultItemsCount++] = sourceSpan[itemIndex]; + // } + //} + + //result._capacity = capacity; + //result._count = resultItemsCount; + //return result; + + throw new NotImplementedException(); + } + public static RecyclableList FindAllIndexes(this RecyclableLongList list, Predicate match) + { + //int sourceItemsCount = list._count; + //if (sourceItemsCount == 0) + //{ + // return new(); + //} + + //ReadOnlySpan sourceSpan = list._memoryBlock; + //RecyclableList result = new(sourceItemsCount >> 3); + //Span resultSpan = result._memoryBlock; + //int capacity = result._capacity, + // resultItemsCount = 0; + + //for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) + //{ + // if (match(sourceSpan[itemIndex])) + // { + // if (resultItemsCount + 1 > capacity) + // { + // capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)resultItemsCount + 1)); + // _ = RecyclableListHelpers.EnsureCapacity(result, resultItemsCount, capacity); + // resultSpan = result._memoryBlock; + // } + + // resultSpan[resultItemsCount++] = itemIndex; + // } + //} + + //result._capacity = capacity; + //result._count = resultItemsCount; + //return result; + + throw new NotImplementedException(); + } + + public static int FindIndex(this RecyclableLongList list, int startIndex, int count, Predicate match) + { + //int sourceItemsCount = Math.Min(startIndex + count, list._count); + //if (sourceItemsCount == 0 || startIndex >= sourceItemsCount) + //{ + // return RecyclableDefaults.ItemNotFoundIndex; + //} + + //ReadOnlySpan sourceSpan = list._memoryBlock; + //for (var itemIndex = startIndex; itemIndex < sourceItemsCount; itemIndex++) + //{ + // if (match(sourceSpan[itemIndex])) + // { + // return itemIndex; + // } + //} + + //return RecyclableDefaults.ItemNotFoundIndex; + + throw new NotImplementedException(); + } + + public static int FindIndex(this RecyclableLongList list, int startIndex, Predicate match) + { + //int sourceItemsCount = list._count; + //if (sourceItemsCount == 0 || startIndex >= sourceItemsCount) + //{ + // return RecyclableDefaults.ItemNotFoundIndex; + //} + + //sourceItemsCount = Math.Min(sourceItemsCount, startIndex + sourceItemsCount); + //ReadOnlySpan sourceSpan = list._memoryBlock; + //for (var itemIndex = startIndex; itemIndex < sourceItemsCount; itemIndex++) + //{ + // if (match(sourceSpan[itemIndex])) + // { + // return itemIndex; + // } + //} + + //return RecyclableDefaults.ItemNotFoundIndex; + + throw new NotImplementedException(); + } + + public static int FindIndex(this RecyclableLongList list, Predicate match) + { + //int sourceItemsCount = list._count; + //if (sourceItemsCount == 0) + //{ + // return RecyclableDefaults.ItemNotFoundIndex; + //} + + //ReadOnlySpan sourceSpan = list._memoryBlock; + //for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) + //{ + // if (match(sourceSpan[itemIndex])) + // { + // return itemIndex; + // } + //} + + //return RecyclableDefaults.ItemNotFoundIndex; + + throw new NotImplementedException(); + } + + public static T? FindLast(this RecyclableLongList list, Predicate match) + { + //if (list._count == 0) + //{ + // return default; + //} + + //ReadOnlySpan sourceSpan = list._memoryBlock; + //for (var itemIndex = list._count - 1; itemIndex >= 0; itemIndex--) + //{ + // if (match(sourceSpan[itemIndex])) + // { + // return sourceSpan[itemIndex]; + // } + //} + + //return default; + + throw new NotImplementedException(); + } + + public static int FindLastIndex(this RecyclableLongList list, int startIndex, int count, Predicate match) + { + //if (count == 0) + //{ + // if (startIndex != -1) + // { + // ThrowHelper.ThrowArgumentOutOfRangeException_Index(); + // } + //} + //else if (count < 0 || startIndex - count + 1 < 0) + //{ + // ThrowHelper.ThrowArgumentOutOfRangeException_Count(); + //} + + //if (startIndex < 0) + //{ + // return RecyclableDefaults.ItemNotFoundIndex; + //} + + //int sourceItemsCount = count; // startIndex - count + 1 >= 0 ? count : startIndex + 1; + //if (sourceItemsCount == 0) + //{ + // return RecyclableDefaults.ItemNotFoundIndex; + //} + + //int lastItemIndex = startIndex - sourceItemsCount; + //ReadOnlySpan sourceSpan = list._memoryBlock; + //for (var itemIndex = startIndex; itemIndex > lastItemIndex; itemIndex--) + //{ + // if (match(sourceSpan[itemIndex])) + // { + // return itemIndex; + // } + //} + + //return RecyclableDefaults.ItemNotFoundIndex; + + throw new NotImplementedException(); + } + + public static int FindLastIndex(this RecyclableLongList list, int startIndex, Predicate match) + { + //if (list._count == 0 || startIndex < 0) + //{ + // return RecyclableDefaults.ItemNotFoundIndex; + //} + + //ReadOnlySpan sourceSpan = list._memoryBlock; + //for (var itemIndex = startIndex; itemIndex >= 0; itemIndex--) + //{ + // if (match(sourceSpan[itemIndex])) + // { + // return itemIndex; + // } + //} + + //return RecyclableDefaults.ItemNotFoundIndex; + + throw new NotImplementedException(); + } + + public static int FindLastIndex(this RecyclableLongList list, Predicate match) + { + //if (list._count == 0) + //{ + // return RecyclableDefaults.ItemNotFoundIndex; + //} + + //ReadOnlySpan sourceSpan = list._memoryBlock; + //for (var itemIndex = list._count - 1; itemIndex >= 0; itemIndex--) + //{ + // if (match(sourceSpan[itemIndex])) + // { + // return itemIndex; + // } + //} + + //return RecyclableDefaults.ItemNotFoundIndex; + + throw new NotImplementedException(); + } + } +} diff --git a/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.IndexOf.cs b/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.IndexOf.cs new file mode 100644 index 0000000..f5cb176 --- /dev/null +++ b/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.IndexOf.cs @@ -0,0 +1,39 @@ +// Ignore Spelling: zzz + +namespace Recyclable.Collections +{ +#pragma warning disable IDE1006 // This intentional so that it shows at the end of IntelliSense list + public static class zzzRecyclableLongListCompatibilityListIndexOf +#pragma warning restore IDE1006 // Naming Styles + { + public static int IndexOf(this RecyclableLongList list, T item, int index) + //=> list._count != 0 + // ? Array.IndexOf(list._memoryBlock, item, index, list._count - index) + // : RecyclableDefaults.ItemNotFoundIndex; + => throw new NotImplementedException(); + + public static int IndexOf(this RecyclableLongList list, T item, int index, int count) + //=> list._count != 0 + // ? Array.IndexOf(list._memoryBlock, item, index, count) + // : RecyclableDefaults.ItemNotFoundIndex; + => throw new NotImplementedException(); + + public static int LastIndexOf(this RecyclableLongList list, T item) + //=> list._count != 0 + // ? Array.LastIndexOf(list._memoryBlock, item, list._count - 1) + // : RecyclableDefaults.ItemNotFoundIndex; + => throw new NotImplementedException(); + + public static int LastIndexOf(this RecyclableLongList list, T item, int index) + //=> list._count != 0 + // ? Array.LastIndexOf(list._memoryBlock, item, index) + // : RecyclableDefaults.ItemNotFoundIndex; + => throw new NotImplementedException(); + + public static int LastIndexOf(this RecyclableLongList list, T item, int index, int count) + //=> list._count != 0 + // ? Array.LastIndexOf(list._memoryBlock, item, index, count) + // : RecyclableDefaults.ItemNotFoundIndex; + => throw new NotImplementedException(); + } +} diff --git a/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.InsertRange.cs b/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.InsertRange.cs new file mode 100644 index 0000000..8d6cd9e --- /dev/null +++ b/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.InsertRange.cs @@ -0,0 +1,420 @@ +// Ignore Spelling: zzz + +using System.Collections; +using System.Numerics; +using System.Runtime.CompilerServices; + +namespace Recyclable.Collections +{ +#pragma warning disable IDE1006 // This intentional so that it shows at the end of IntelliSense list + public static class zzzRecyclableLongListCompatibilityListInsertRange +#pragma warning restore IDE1006 // Naming Styles + { + private static void InsertRangeEnumerated(this RecyclableLongList list, int index, IEnumerable items, int growByCount) + { + //var enumerator = items.GetEnumerator(); + //if (!enumerator.MoveNext()) + //{ + // return; + //} + + //int capacity = list._capacity, + // added = 0, + // available = capacity - list._count, + // i, + // movingBlockLength = list._count - index; + + //T[] memoryBlock = list._memoryBlock; + //if (available > 0) + //{ + // Array.Copy(memoryBlock, index, memoryBlock, capacity - movingBlockLength, movingBlockLength); + //} + + //Span memorySpan = memoryBlock; + //do + //{ + // if (index + available + movingBlockLength > capacity) + // { + // var capacityBeforeIncrease = capacity; + // capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)(capacity + growByCount))); + // _ = RecyclableListHelpers.EnsureCapacity(list, memoryBlock.Length, capacity); + // memorySpan = memoryBlock = list._memoryBlock; + // available = capacity - index - movingBlockLength; + // Array.Copy(memoryBlock, capacityBeforeIncrease - movingBlockLength, memoryBlock, capacity - movingBlockLength, movingBlockLength); + // } + + // for (i = 0; i < available; i++) + // { + // memorySpan[index++] = enumerator.Current; + // if (!enumerator.MoveNext()) + // { + // added++; + // break; + // } + // } + + // added += i; + //} + //while (i == available); + + //if (i != available) + //{ + // Array.Copy(memoryBlock, capacity - movingBlockLength, memoryBlock, index, movingBlockLength); + // if (RecyclableList._needsClearing) + // { + // Array.Clear(memoryBlock, capacity - movingBlockLength, movingBlockLength); + // } + //} + + //list._count += added; + //list._capacity = capacity; + + throw new NotImplementedException(); + } + + private static void InsertRangeWithKnownCount(this RecyclableLongList list, int index, IEnumerable items, int currentItemsCount, int requiredAdditionalCapacity) + { + //list._capacity = RecyclableListHelpers.EnsureCapacity(list, currentItemsCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)(currentItemsCount + requiredAdditionalCapacity)))); + + //// TODO: Count should be requiredAdditionalCapacity, we need to move as many items as many we're inserting + //Array.Copy(list._memoryBlock, index, list._memoryBlock, index + requiredAdditionalCapacity, list._count - index); + //Span memorySpan = list._memoryBlock; + //foreach (var item in items) + //{ + // memorySpan[index++] = item; + //} + + //list._count += requiredAdditionalCapacity; + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void InsertRange(this RecyclableLongList list, int index, in Array items) + { + //if (list._capacity < list._count + items.Length) + //{ + // list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length)))); + //} + + //T[] memoryBlock = list._memoryBlock; + //// TODO: Count should be items.Count, we need to move as many items as many we're inserting + //Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index); + //Array.Copy(items, items.GetLowerBound(0), memoryBlock, index, items.Length); + //list._count += items.Length; + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void InsertRange(this RecyclableLongList list, int index, in T[] items) + { + //if (list._capacity < list._count + items.Length) + //{ + // list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length)))); + //} + + //T[] memoryBlock = list._memoryBlock; + //// TODO: Count should be items.Count, we need to move as many items as many we're inserting + //Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index); + //new ReadOnlySpan(items).CopyTo(new Span(memoryBlock, index, items.Length)); + //list._count += items.Length; + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void InsertRange(this RecyclableLongList list, int index, ReadOnlySpan items) + { + //if (list._capacity < list._count + items.Length) + //{ + // list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length)))); + //} + + //T[] memoryBlock = list._memoryBlock; + //// TODO: Count should be items.Count, we need to move as many items as many we're inserting + //Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index); + //items.CopyTo(new Span(memoryBlock, index, items.Length)); + //list._count += items.Length; + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void InsertRange(this RecyclableLongList list, int index, Span items) + { + //if (list._capacity < list._count + items.Length) + //{ + // list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Length)))); + //} + + //T[] memoryBlock = list._memoryBlock; + //// TODO: Count should be items.Count, we need to move as many items as many we're inserting + //Array.Copy(memoryBlock, index, memoryBlock, index + items.Length, list._count - index); + //items.CopyTo(new Span(memoryBlock, index, items.Length)); + //list._count += items.Length; + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void InsertRange(this RecyclableLongList list, int index, List items) + { + //if (list._capacity < list._count + items.Count) + //{ + // list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Count)))); + //} + + //T[] memoryBlock = list._memoryBlock; + //// TODO: Count should be items.Count, we need to move as many items as many we're inserting + //Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index); + //items.CopyTo(memoryBlock, index); + //list._count += items.Count; + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void InsertRange(this RecyclableLongList list, int index, ICollection items) + { + //if (list._capacity < list._count + items.Count) + //{ + // list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Count)))); + //} + + //T[] memoryBlock = list._memoryBlock; + //// TODO: Count should be items.Count, we need to move as many items as many we're inserting + //Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index); + //items.CopyTo(list._memoryBlock, index); + //list._count += items.Count; + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void InsertRange(this RecyclableLongList list, int index, ICollection items) + { + //if (list._capacity < list._count + items.Count) + //{ + // list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items.Count)))); + //} + + //T[] memoryBlock = list._memoryBlock; + //// TODO: Count should be items.Count, we need to move as many items as many we're inserting + //Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index); + //items.CopyTo(memoryBlock, index); + //list._count += items.Count; + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void InsertRange(this RecyclableLongList list, int index, RecyclableList items) + { + //if (list._capacity < list._count + items._count) + //{ + // list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + items._count)))); + //} + + //T[] memoryBlock = list._memoryBlock; + //// TODO: Count should be items.Count, we need to move as many items as many we're inserting + //Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, list._count - index); + //new ReadOnlySpan(items._memoryBlock, 0, items._count).CopyTo(new(list._memoryBlock, index, items._count)); + //list._count += items._count; + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void InsertRange(this RecyclableLongList list, int index, RecyclableLongList items) + { + //if (items._longCount == 0) + //{ + // return; + //} + + //int oldCount = list._count; + //long sourceItemsCount = items._longCount; + //if (oldCount + sourceItemsCount > int.MaxValue) + //{ + // ThrowHelper.ThrowArgumentOutOfRangeException(nameof(items), $"The total number of items in source and target table exceeds the maximum capacity of {nameof(RecyclableList)}, equal {int.MaxValue}. Please consider using {nameof(RecyclableLongList)}, instead"); + //} + + //int targetCapacity = oldCount + (int)sourceItemsCount; + //if (list._capacity < targetCapacity) + //{ + // list._capacity = RecyclableListHelpers.EnsureCapacity(list, oldCount, checked((int)BitOperations.RoundUpToPowerOf2((uint)targetCapacity))); + //} + + //T[] memoryBlock = list._memoryBlock; + //Array.Copy(memoryBlock, index, memoryBlock, index + items.Count, oldCount - index); + //Span targetSpan = new(list._memoryBlock, index, list._capacity - index), + // itemsSpan; + + //int blockIndex, + // sourceBlockSize = items._blockSize, + // lastBlockIndex = (int)(sourceItemsCount >> items._blockSizePow2BitShift) - 1; + + //for (blockIndex = 0; blockIndex <= lastBlockIndex; blockIndex++) + //{ + // itemsSpan = new(items._memoryBlocks[blockIndex], 0, sourceBlockSize); + // itemsSpan.CopyTo(targetSpan); + // targetSpan = targetSpan[sourceBlockSize..]; + //} + + //if (blockIndex == 0) + //{ + // itemsSpan = new(items._memoryBlocks[blockIndex], 0, (int)sourceItemsCount); + // itemsSpan.CopyTo(targetSpan); + //} + //else if (blockIndex <= items._lastBlockWithData) + //{ + // itemsSpan = new(items._memoryBlocks[blockIndex], 0, items._nextItemIndex > 0 ? items._nextItemIndex : sourceBlockSize); + // itemsSpan.CopyTo(targetSpan); + //} + + //list._count = targetCapacity; + //list._version++; + + throw new NotImplementedException(); + } + + public static void InsertRange(this RecyclableLongList list, int index, IEnumerable items, int growByCount = RecyclableDefaults.MinPooledArrayLength) + { + //var enumerator = items.GetEnumerator(); + //if (!enumerator.MoveNext()) + //{ + // return; + //} + + //int capacity = list._capacity, + // added = 0, + // available = capacity - list._count, + // i, + // movingBlockLength = list._count - index; + + //T[] memoryBlock = list._memoryBlock; + //if (available > 0) + //{ + // Array.Copy(memoryBlock, index, memoryBlock, capacity - movingBlockLength, movingBlockLength); + //} + + //Span memorySpan = memoryBlock; + //do + //{ + // if (index + available + movingBlockLength > capacity) + // { + // var capacityBeforeIncrease = capacity; + // capacity = checked((int)BitOperations.RoundUpToPowerOf2((uint)(capacity + growByCount))); + // _ = RecyclableListHelpers.EnsureCapacity(list, memoryBlock.Length, capacity); + // memorySpan = memoryBlock = list._memoryBlock; + // available = capacity - index - movingBlockLength; + // Array.Copy(memoryBlock, capacityBeforeIncrease - movingBlockLength, memoryBlock, capacity - movingBlockLength, movingBlockLength); + // } + + // for (i = 0; i < available; i++) + // { + // memorySpan[index++] = (T)enumerator.Current; + // if (!enumerator.MoveNext()) + // { + // added++; + // break; + // } + // } + + // added += i; + //} + //while (i == available); + + //if (i != available) + //{ + // Array.Copy(memoryBlock, capacity - movingBlockLength, memoryBlock, index, movingBlockLength); + // if (RecyclableList._needsClearing) + // { + // Array.Clear(memoryBlock, capacity - movingBlockLength, movingBlockLength); + // } + //} + + //list._count += added; + //list._capacity = capacity; + + throw new NotImplementedException(); + } + + public static void InsertRange(this RecyclableLongList list, int index, IReadOnlyList items) + { + //int sourceItemsCount = items.Count; + //if (list._capacity < list._count + sourceItemsCount) + //{ + // list._capacity = RecyclableListHelpers.EnsureCapacity(list, list._count, checked((int)BitOperations.RoundUpToPowerOf2((uint)(list._count + sourceItemsCount)))); + //} + + //Array.Copy(list._memoryBlock, index, list._memoryBlock, index + sourceItemsCount, Math.Min(list.Count - index, sourceItemsCount)); + //Span memorySpan = new(list._memoryBlock, index, sourceItemsCount); + //for (var sourceItemIndex = 0; sourceItemIndex < sourceItemsCount; sourceItemIndex++) + //{ + // memorySpan[sourceItemIndex] = items[sourceItemIndex]; + //} + + //list._count += sourceItemsCount; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.NoInlining | MethodImplOptions.AggressiveOptimization)] + public static void InsertRange(this RecyclableLongList list, int index, IEnumerable items, int growByCount = RecyclableDefaults.MinPooledArrayLength) + { + //if (items is RecyclableList sourceRecyclableList) + //{ + // InsertRange(list, index, sourceRecyclableList); + //} + //else if (items is RecyclableLongList sourceRecyclableLongList) + //{ + // InsertRange(list, index, sourceRecyclableLongList); + //} + //else if (items is T[] sourceArray) + //{ + // InsertRange(list, index, sourceArray); + //} + //else if (items is Array sourceArrayWithObjects) + //{ + // InsertRange(list, index, sourceArrayWithObjects); + //} + //else if (items is List sourceList) + //{ + // InsertRange(list, index, sourceList); + //} + //else if (items is ICollection sourceICollection) + //{ + // InsertRange(list, index, sourceICollection); + //} + //else if (items is ICollection sourceICollectionWithObjects) + //{ + // InsertRange(list, index, sourceICollectionWithObjects); + //} + //else if (items is IReadOnlyList sourceIReadOnlyList) + //{ + // InsertRange(list, index, sourceIReadOnlyList); + //} + //else if (items.TryGetNonEnumeratedCount(out var requiredAdditionalCapacity) && requiredAdditionalCapacity != 0) + //{ + // InsertRangeWithKnownCount(list, index, items, list._count, requiredAdditionalCapacity); + //} + //else + //{ + // InsertRangeEnumerated(list, index, items, growByCount); + //} + + throw new NotImplementedException(); + } + } +} \ No newline at end of file diff --git a/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.cs b/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.cs new file mode 100644 index 0000000..04e36ca --- /dev/null +++ b/Recyclable.Collections.Compatibility.List/RecyclableLongList.Compatibility.List.cs @@ -0,0 +1,289 @@ +// Ignore Spelling: zzz + +using System.Collections.ObjectModel; +using System.Numerics; +using System.Runtime.CompilerServices; +using Recyclable.Collections.Pools; + +namespace Recyclable.Collections +{ + +#pragma warning disable IDE1006 // This intentional so that it shows at the end of IntelliSense list + public static class zzzRecyclableLongListCompatibilityList +#pragma warning restore IDE1006 // Naming Styles + { + public static ReadOnlyCollection AsReadOnly(this RecyclableLongList list) => new(list); + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static int BinarySearch(this RecyclableLongList list, T item) + { + if (list._longCount == 0) + { + return RecyclableDefaults.ItemNotFoundIndex; + } + + int blockIndex = 0, + blockSize = list._blockSize, + itemIndex; + var comparer = Comparer.Default; + var lastFullBlockIndex = list._lastBlockWithData; + Span memoryBlocksSpan = list._memoryBlocks; + while (blockIndex < lastFullBlockIndex) + { + itemIndex = new Span(memoryBlocksSpan[blockIndex], 0, blockSize).BinarySearch(item, comparer); + if (itemIndex >= 0) + { + return (blockIndex << list._blockSizePow2BitShift) + itemIndex; + } + + blockIndex++; + } + + itemIndex = new Span(memoryBlocksSpan[blockIndex], 0, list._nextItemIndex != 0 ? list._nextItemIndex : blockSize).BinarySearch(item, comparer); + return itemIndex >= 0 ? (blockIndex << list._blockSizePow2BitShift) + itemIndex : RecyclableDefaults.ItemNotFoundIndex; + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static int BinarySearch(this RecyclableLongList list, T item, IComparer? comparer) + //=> Array.BinarySearch(list._memoryBlock, 0, list._count, item, comparer); + => throw new NotImplementedException(); + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static int BinarySearch(this RecyclableLongList list, int index, int count, T item, IComparer? comparer) + //=> Array.BinarySearch(list._memoryBlock, index, count, item, comparer); + => throw new NotImplementedException(); + + public static RecyclableList ConvertAll(this RecyclableLongList list, Converter converter) + { + //int itemsCount = list._count; + //if (itemsCount == 0) + //{ + // return new(); + //} + + //RecyclableList result = new(itemsCount); + //TOutput[] resultSpan = result._memoryBlock; + //ReadOnlySpan sourceSpan = list._memoryBlock; + //for (int bufferIndex = 0; bufferIndex < itemsCount; bufferIndex++) + //{ + // resultSpan[bufferIndex] = converter(sourceSpan[bufferIndex]); + //} + + //result._count = itemsCount; + //return result; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static void CopyTo(this RecyclableLongList list, T[] array) + //=> Array.Copy(list._memoryBlock, array, list._count); + => throw new NotImplementedException(); + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static void CopyTo(this RecyclableLongList list, int index, T[] array, int arrayIndex, int count) + //=> Array.Copy(list._memoryBlock, index, array, arrayIndex, count); + => throw new NotImplementedException(); + + public static void ForEach(this RecyclableLongList list, Action action) + { + //int sourceItemsCount = list._count; + //if (sourceItemsCount == 0) + //{ + // return; + //} + + //ReadOnlySpan sourceSpan = list._memoryBlock; + //for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) + //{ + // action(sourceSpan[itemIndex]); + //} + + throw new NotImplementedException(); + } + + public static RecyclableList GetRange(this RecyclableLongList list, int index, int count) + { + //int sourceItemsCount = index + count <= list._count ? count : list._count - index; + //if (sourceItemsCount <= 0) + //{ + // return new(); + //} + + //ReadOnlySpan sourceSpan = list._memoryBlock; + //RecyclableList result = new(sourceItemsCount); + //Span targetSpan = result._memoryBlock; + //int resultItemsCount = 0; + //sourceItemsCount += index; + //for (var itemIndex = index; itemIndex < sourceItemsCount; itemIndex++) + //{ + // targetSpan[resultItemsCount++] = sourceSpan[itemIndex]; + //} + + //result._count = resultItemsCount; + //return result; + + throw new NotImplementedException(); + } + + public static int RemoveAll(this RecyclableLongList list, Predicate match) + { + //using var allIndexes = zzzRecyclableListCompatibilityListFind.FindAllIndexes(list, match); + //int foundItemsCount = allIndexes._count; + //if (foundItemsCount == 0) + //{ + // return foundItemsCount; + //} + + //for (int removed = 0; removed < foundItemsCount; removed++) + //{ + // var indexToRemove = allIndexes[removed] - removed; + // Array.Copy(list._memoryBlock, indexToRemove + 1, list._memoryBlock, indexToRemove, list._count - indexToRemove - removed - 1); + //} + + //if (RecyclableList._needsClearing) + //{ + // Array.Clear(list._memoryBlock, list._count - foundItemsCount, foundItemsCount); + //} + + //list._count -= foundItemsCount; + //list._version++; + //return foundItemsCount; + + throw new NotImplementedException(); + } + + public static void RemoveRange(this RecyclableLongList list, int index, int count) + { + //int oldCount = list._count; + //count = count - index + 1 <= oldCount ? count : oldCount - index + 1; + //if (count == 0) + //{ + // return; + //} + + //if (index + count < oldCount) + //{ + // Array.Copy(list._memoryBlock, index + count, list._memoryBlock, index, oldCount - count - index); + //} + + //if (RecyclableList._needsClearing) + //{ + // Array.Clear(list._memoryBlock, oldCount - count, count); + //} + + //list._count -= count; + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static void Reverse(this RecyclableLongList list) + { + //Array.Reverse(list._memoryBlock, 0, list._count); + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static void Reverse(this RecyclableLongList list, int index, int count) + { + //Array.Reverse(list._memoryBlock, index, count); + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static void Sort(this RecyclableLongList list) + { + //Array.Sort(list._memoryBlock, 0, list._count); + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static void Sort(this RecyclableLongList list, Comparison comparison) + { + //Array.Sort(list._memoryBlock, 0, list._count, new ComparisonToComparerAdapter(comparison)); + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static void Sort(this RecyclableLongList list, IComparer? comparer) + { + //Array.Sort(list._memoryBlock, 0, list._count, comparer); + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static void Sort(this RecyclableLongList list, int index, int count, IComparer? comparer) + { + //Array.Sort(list._memoryBlock, index, count, comparer); + //list._version++; + + throw new NotImplementedException(); + } + + [MethodImpl(MethodImplOptions.AggressiveInlining | MethodImplOptions.AggressiveOptimization)] + public static T[] ToArray(this RecyclableLongList list) + { + //T[] result = new T[list._count]; + //new ReadOnlySpan(list._memoryBlock, 0, list._count).CopyTo(result); + //return result; + + throw new NotImplementedException(); + } + + public static void TrimExcess(this RecyclableLongList list) + { + //var requiredCapacity = list._count >= RecyclableDefaults.InitialCapacity ? list._count : RecyclableDefaults.InitialCapacity; + + //T[] oldMemoryBlock = list._memoryBlock; + //T[] result = requiredCapacity >= RecyclableDefaults.MinPooledArrayLength && BitOperations.IsPow2(requiredCapacity) + // ? RecyclableArrayPool.RentShared(requiredCapacity) + // : new T[requiredCapacity]; + + //new ReadOnlySpan(oldMemoryBlock, 0, list._count).CopyTo(result); + + //if (oldMemoryBlock.Length >= RecyclableDefaults.MinPooledArrayLength) + //{ + // RecyclableArrayPool.ReturnShared(oldMemoryBlock, RecyclableList._needsClearing); + //} + + //list._memoryBlock = result; + //list._capacity = requiredCapacity; + + throw new NotImplementedException(); + } + + public static bool TrueForAll(this RecyclableLongList list, Predicate match) + { + //int sourceItemsCount = list._count; + //if (sourceItemsCount == 0) + //{ + // return false; + //} + + //ReadOnlySpan sourceSpan = list._memoryBlock; + //for (var itemIndex = 0; itemIndex < sourceItemsCount; itemIndex++) + //{ + // if (!match(sourceSpan[itemIndex])) + // { + // return false; + // } + //} + + //return true; + + throw new NotImplementedException(); + } + } +}