public void SwapIndexRangeToBack(int sectionIndex, int sectionLength, int swapIndex, int swapRange) { if (sectionIndex < 0) { throw new ArgumentException($"{nameof(sectionIndex)} must be 0 or higher."); } if (sectionLength < 0) { throw new ArgumentException($"{nameof(sectionLength)} must be 0 or higher."); } if (swapIndex < 0) { throw new ArgumentException($"{nameof(swapIndex)} must be positive."); } if (swapIndex + swapRange > sectionLength) { throw new ArgumentException($"{nameof(swapIndex)} ({swapIndex}) + {nameof(swapRange)} ({swapRange}) must be smaller than {nameof(sectionIndex)} ({sectionIndex})."); } if (sectionLength == 0 || swapRange == 0) { return; } var lengthBehindSwapIndex = sectionLength - swapIndex; var tempOffset = indexToID.Length; // aaaaaabbbbcc .... // aaaaaabbbbcc .... bbbb // | ^ // |___________| // Copy the original indices to beyond the end of the list // Make space for these indices, hopefully the index list already has the capacity for // this and no allocation needs to be made indexToID.Resize(tempOffset + swapRange, NativeArrayOptions.UninitializedMemory); indexToID.MemMove(tempOffset, sectionIndex + swapIndex, swapRange); // aaaaaabbbbcc .... bbbb // aaaaaaccbbcc .... bbbb // ^ | // |__| // Move indices behind our swapIndex/swapRange on top of where our swap region begins var count = lengthBehindSwapIndex - swapRange; indexToID.MemMove(sectionIndex + swapIndex, sectionIndex + swapIndex + swapRange, count); // aaaaaaccbbcc .... bbbb // aaaaaaccbbbb .... bbbb // ^ | // |___________| // Copy the original indices to the end indexToID.MemMove(sectionIndex + swapIndex + count, tempOffset, swapRange); // aaaaaaccbbbb .... bbbb // aaaaaaccbbbb .... // Resize indices list to remove the temporary data, this is basically just // indexToID.length = tempOffset indexToID.Resize(tempOffset, NativeArrayOptions.UninitializedMemory); for (int index = sectionIndex + swapIndex, lastIndex = sectionIndex + sectionLength; index < lastIndex; index++) { var idInternal = indexToID[index] - 1; var idLookup = idToIndex[idInternal]; idLookup.index = index; idToIndex[idInternal] = idLookup; } }