public static void Convert(Chunk *srcChunk, int srcIndex, Chunk *dstChunk, int dstIndex)
        {
            var srcArch = srcChunk->Archetype;
            var dstArch = dstChunk->Archetype;

            //Debug.Log($"Convert {EntityManager.EntityManagerDebug.GetArchetypeDebugString(srcArch)} to {EntityManager.EntityManagerDebug.GetArchetypeDebugString(dstArch)}");

            var srcI = 0;
            var dstI = 0;

            while (srcI < srcArch->TypesCount && dstI < dstArch->TypesCount)
            {
                var src = srcChunk->Buffer + srcArch->Offsets[srcI] + srcIndex * srcArch->SizeOfs[srcI];
                var dst = dstChunk->Buffer + dstArch->Offsets[dstI] + dstIndex * dstArch->SizeOfs[dstI];

                if (srcArch->Types[srcI] < dstArch->Types[dstI])
                {
                    // Clear any buffers we're not going to keep.
                    if (srcArch->Types[srcI].IsBuffer)
                    {
                        BufferHeader.Destroy((BufferHeader *)src);
                    }

                    ++srcI;
                }
                else if (srcArch->Types[srcI] > dstArch->Types[dstI])
                {
                    // Clear components in the destination that aren't copied

                    if (dstArch->Types[dstI].IsBuffer)
                    {
                        BufferHeader.Initialize((BufferHeader *)dst, dstArch->Types[dstI].BufferCapacity);
                    }
                    else
                    {
                        UnsafeUtility.MemClear(dst, dstArch->SizeOfs[dstI]);
                    }

                    ++dstI;
                }
                else
                {
                    UnsafeUtility.MemCpy(dst, src, srcArch->SizeOfs[srcI]);

                    // Poison source buffer to make sure there is no aliasing.
                    if (srcArch->Types[srcI].IsBuffer)
                    {
                        BufferHeader.Initialize((BufferHeader *)src, srcArch->Types[srcI].BufferCapacity);
                    }

                    ++srcI;
                    ++dstI;
                }
            }

            // Handle remaining components in the source that aren't copied
            for (; srcI < srcArch->TypesCount; ++srcI)
            {
                var src = srcChunk->Buffer + srcArch->Offsets[srcI] + srcIndex * srcArch->SizeOfs[srcI];
                if (srcArch->Types[srcI].IsBuffer)
                {
                    BufferHeader.Destroy((BufferHeader *)src);
                }
            }

            // Clear remaining components in the destination that aren't copied
            for (; dstI < dstArch->TypesCount; ++dstI)
            {
                var dst = dstChunk->Buffer + dstArch->Offsets[dstI] + dstIndex * dstArch->SizeOfs[dstI];
                if (dstArch->Types[dstI].IsBuffer)
                {
                    BufferHeader.Initialize((BufferHeader *)dst, dstArch->Types[dstI].BufferCapacity);
                }
                else
                {
                    UnsafeUtility.MemClear(dst, dstArch->SizeOfs[dstI]);
                }
            }
        }
        public static void Convert(Chunk *srcChunk, int srcIndex, Chunk *dstChunk, int dstIndex, int count, ref EntityComponentStore entityComponentStore)
        {
            Assert.IsFalse(srcChunk == dstChunk);
            var srcArch = srcChunk->Archetype;
            var dstArch = dstChunk->Archetype;

            if (srcArch != dstArch)
            {
                Assert.IsFalse(srcArch == null);
            }

            var srcI = srcArch->NonZeroSizedTypesCount - 1;
            var dstI = dstArch->NonZeroSizedTypesCount - 1;

            var sourceTypesToDealloc      = stackalloc int[srcI + 1];
            int sourceTypesToDeallocCount = 0;

            while (dstI >= 0)
            {
                var srcType = srcArch->Types[srcI];
                var dstType = dstArch->Types[dstI];

                if (srcType > dstType)
                {
                    //Type in source is not moved so deallocate it
                    sourceTypesToDealloc[sourceTypesToDeallocCount++] = srcI;
                    --srcI;
                    continue;
                }

                var srcStride = srcArch->SizeOfs[srcI];
                var dstStride = dstArch->SizeOfs[dstI];
                var src       = srcChunk->Buffer + srcArch->Offsets[srcI] + srcIndex * srcStride;
                var dst       = dstChunk->Buffer + dstArch->Offsets[dstI] + dstIndex * dstStride;

                if (srcType == dstType)
                {
                    UnsafeUtility.MemCpy(dst, src, count * srcStride);
                    --srcI;
                    --dstI;
                }
                else
                {
                    if (dstType.IsBuffer)
                    {
                        InitializeBuffersInChunk(dst, count, dstStride, dstArch->BufferCapacities[dstI]);
                    }
                    else
                    {
                        UnsafeUtility.MemClear(dst, count * dstStride);
                    }
                    --dstI;
                }
            }

            if (sourceTypesToDeallocCount == 0)
            {
                return;
            }

            sourceTypesToDealloc[sourceTypesToDeallocCount] = 0;

            int iDealloc = 0;

            if (sourceTypesToDealloc[iDealloc] >= srcArch->FirstManagedComponent)
            {
                var freeCommandHandle = entityComponentStore.ManagedChangesTracker.BeginFreeManagedComponentCommand();
                do
                {
                    srcI = sourceTypesToDealloc[iDealloc];
                    var srcStride = srcArch->SizeOfs[srcI];
                    var src       = srcChunk->Buffer + srcArch->Offsets[srcI] + srcIndex * srcStride;

                    var a = (int *)src;
                    for (int i = 0; i < count; i++)
                    {
                        var managedComponentIndex = a[i];
                        if (managedComponentIndex == 0)
                        {
                            continue;
                        }
                        entityComponentStore.FreeManagedComponentIndex(managedComponentIndex);
                        entityComponentStore.ManagedChangesTracker.AddToFreeManagedComponentCommand(managedComponentIndex);
                    }
                } while ((sourceTypesToDealloc[++iDealloc] >= srcArch->FirstManagedComponent));
                entityComponentStore.ManagedChangesTracker.EndDeallocateManagedComponentCommand(freeCommandHandle);
            }

            while (sourceTypesToDealloc[iDealloc] >= srcArch->FirstBufferComponent)
            {
                srcI = sourceTypesToDealloc[iDealloc];
                var srcStride = srcArch->SizeOfs[srcI];
                var srcPtr    = srcChunk->Buffer + srcArch->Offsets[srcI] + srcIndex * srcStride;
                for (int i = 0; i < count; i++)
                {
                    BufferHeader.Destroy((BufferHeader *)srcPtr);
                    srcPtr += srcStride;
                }
                ++iDealloc;
            }
        }