diff --git a/src/ImageSharp/Colors/Color.cs b/src/ImageSharp/Colors/Color.cs
index 469774b348..8a869935c1 100644
--- a/src/ImageSharp/Colors/Color.cs
+++ b/src/ImageSharp/Colors/Color.cs
@@ -112,6 +112,9 @@ namespace ImageSharp
this.packedValue = packed;
}
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Gets or sets the red component.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/Alpha8.cs b/src/ImageSharp/Colors/PackedPixel/Alpha8.cs
index 485725d71a..1181eb9e47 100644
--- a/src/ImageSharp/Colors/PackedPixel/Alpha8.cs
+++ b/src/ImageSharp/Colors/PackedPixel/Alpha8.cs
@@ -26,6 +26,9 @@ namespace ImageSharp
///
public byte PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/Argb.cs b/src/ImageSharp/Colors/PackedPixel/Argb.cs
index bef986fb9c..1b97d2337a 100644
--- a/src/ImageSharp/Colors/PackedPixel/Argb.cs
+++ b/src/ImageSharp/Colors/PackedPixel/Argb.cs
@@ -109,6 +109,9 @@ namespace ImageSharp
///
public uint PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Gets or sets the red component.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/Bgr565.cs b/src/ImageSharp/Colors/PackedPixel/Bgr565.cs
index ebe8d25335..41b2bdc2e0 100644
--- a/src/ImageSharp/Colors/PackedPixel/Bgr565.cs
+++ b/src/ImageSharp/Colors/PackedPixel/Bgr565.cs
@@ -39,6 +39,9 @@ namespace ImageSharp
///
public ushort PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/Bgra4444.cs b/src/ImageSharp/Colors/PackedPixel/Bgra4444.cs
index ccd6ab1f3e..99659a36bc 100644
--- a/src/ImageSharp/Colors/PackedPixel/Bgra4444.cs
+++ b/src/ImageSharp/Colors/PackedPixel/Bgra4444.cs
@@ -38,6 +38,9 @@ namespace ImageSharp
///
public ushort PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/Bgra5551.cs b/src/ImageSharp/Colors/PackedPixel/Bgra5551.cs
index a7a2e899a5..86864fd485 100644
--- a/src/ImageSharp/Colors/PackedPixel/Bgra5551.cs
+++ b/src/ImageSharp/Colors/PackedPixel/Bgra5551.cs
@@ -40,6 +40,9 @@ namespace ImageSharp
///
public ushort PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/BulkPixelOperations.cs b/src/ImageSharp/Colors/PackedPixel/BulkPixelOperations.cs
new file mode 100644
index 0000000000..c914b3921c
--- /dev/null
+++ b/src/ImageSharp/Colors/PackedPixel/BulkPixelOperations.cs
@@ -0,0 +1,56 @@
+namespace ImageSharp
+{
+ using System.Numerics;
+
+ public unsafe class BulkPixelOperations
+ where TColor : struct, IPixel
+ {
+ public static BulkPixelOperations Instance { get; } = default(TColor).BulkOperations;
+
+ internal virtual void PackFromVector4(
+ ArrayPointer sourceVectors,
+ ArrayPointer destColors,
+ int count)
+ {
+ }
+
+ internal virtual void PackToVector4(
+ ArrayPointer sourceColors,
+ ArrayPointer destVectors,
+ int count)
+ {
+ }
+
+ internal virtual void PackToXyzBytes(ArrayPointer sourceColors, ArrayPointer destBytes, int count)
+ {
+ }
+
+ internal virtual void PackFromXyzBytes(ArrayPointer sourceBytes, ArrayPointer destColors, int count)
+ {
+ }
+
+ internal virtual void PackToXyzwBytes(ArrayPointer sourceColors, ArrayPointer destBytes, int count)
+ {
+ }
+
+ internal virtual void PackFromXyzwBytes(ArrayPointer sourceBytes, ArrayPointer destColors, int count)
+ {
+ }
+
+ internal virtual void PackToZyxBytes(ArrayPointer sourceColors, ArrayPointer destBytes, int count)
+ {
+ }
+
+ internal virtual void PackFromZyxBytes(ArrayPointer sourceBytes, ArrayPointer destColors, int count)
+ {
+ }
+
+ internal virtual void PackToZyxwBytes(ArrayPointer sourceColors, ArrayPointer destBytes, int count)
+ {
+ }
+
+ internal virtual void PackFromZyxwBytes(ArrayPointer sourceBytes, ArrayPointer destColors, int count)
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/ImageSharp/Colors/PackedPixel/Byte4.cs b/src/ImageSharp/Colors/PackedPixel/Byte4.cs
index 9d5eb9be81..5712027d96 100644
--- a/src/ImageSharp/Colors/PackedPixel/Byte4.cs
+++ b/src/ImageSharp/Colors/PackedPixel/Byte4.cs
@@ -41,6 +41,9 @@ namespace ImageSharp
///
public uint PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/HalfSingle.cs b/src/ImageSharp/Colors/PackedPixel/HalfSingle.cs
index acfa639b70..0bc82c3a61 100644
--- a/src/ImageSharp/Colors/PackedPixel/HalfSingle.cs
+++ b/src/ImageSharp/Colors/PackedPixel/HalfSingle.cs
@@ -36,6 +36,9 @@ namespace ImageSharp
///
public ushort PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/HalfVector2.cs b/src/ImageSharp/Colors/PackedPixel/HalfVector2.cs
index e02c226dd7..778f86e0f6 100644
--- a/src/ImageSharp/Colors/PackedPixel/HalfVector2.cs
+++ b/src/ImageSharp/Colors/PackedPixel/HalfVector2.cs
@@ -45,6 +45,9 @@ namespace ImageSharp
///
public uint PackedValue { get; set; }
+
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
///
/// Compares two objects for equality.
diff --git a/src/ImageSharp/Colors/PackedPixel/HalfVector4.cs b/src/ImageSharp/Colors/PackedPixel/HalfVector4.cs
index 7c7f640e49..c24553d3f3 100644
--- a/src/ImageSharp/Colors/PackedPixel/HalfVector4.cs
+++ b/src/ImageSharp/Colors/PackedPixel/HalfVector4.cs
@@ -49,6 +49,9 @@ namespace ImageSharp
///
public ulong PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/IPixel.cs b/src/ImageSharp/Colors/PackedPixel/IPixel.cs
index 1c3e20a7e4..c17fe86ccf 100644
--- a/src/ImageSharp/Colors/PackedPixel/IPixel.cs
+++ b/src/ImageSharp/Colors/PackedPixel/IPixel.cs
@@ -15,6 +15,10 @@ namespace ImageSharp
public interface IPixel : IPixel, IEquatable
where TSelf : struct, IPixel
{
+ ///
+ /// Gets the instance for this pixel type.
+ ///
+ BulkPixelOperations BulkOperations { get; }
}
///
diff --git a/src/ImageSharp/Colors/PackedPixel/NormalizedByte2.cs b/src/ImageSharp/Colors/PackedPixel/NormalizedByte2.cs
index 116a681726..d425806c27 100644
--- a/src/ImageSharp/Colors/PackedPixel/NormalizedByte2.cs
+++ b/src/ImageSharp/Colors/PackedPixel/NormalizedByte2.cs
@@ -51,6 +51,9 @@ namespace ImageSharp
///
public ushort PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/NormalizedByte4.cs b/src/ImageSharp/Colors/PackedPixel/NormalizedByte4.cs
index 7aaa30c520..cba3f0e863 100644
--- a/src/ImageSharp/Colors/PackedPixel/NormalizedByte4.cs
+++ b/src/ImageSharp/Colors/PackedPixel/NormalizedByte4.cs
@@ -52,6 +52,9 @@ namespace ImageSharp
///
public uint PackedValue { get; set; }
+
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
///
/// Compares two objects for equality.
diff --git a/src/ImageSharp/Colors/PackedPixel/NormalizedShort2.cs b/src/ImageSharp/Colors/PackedPixel/NormalizedShort2.cs
index 2f4ef89d65..4bc7f94277 100644
--- a/src/ImageSharp/Colors/PackedPixel/NormalizedShort2.cs
+++ b/src/ImageSharp/Colors/PackedPixel/NormalizedShort2.cs
@@ -51,6 +51,9 @@ namespace ImageSharp
///
public uint PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/NormalizedShort4.cs b/src/ImageSharp/Colors/PackedPixel/NormalizedShort4.cs
index 60c5c9805a..c848b72369 100644
--- a/src/ImageSharp/Colors/PackedPixel/NormalizedShort4.cs
+++ b/src/ImageSharp/Colors/PackedPixel/NormalizedShort4.cs
@@ -53,6 +53,9 @@ namespace ImageSharp
///
public ulong PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/Rg32.cs b/src/ImageSharp/Colors/PackedPixel/Rg32.cs
index 9e5e5a711c..9eb2247c9b 100644
--- a/src/ImageSharp/Colors/PackedPixel/Rg32.cs
+++ b/src/ImageSharp/Colors/PackedPixel/Rg32.cs
@@ -36,6 +36,9 @@ namespace ImageSharp
///
public uint PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/Rgba1010102.cs b/src/ImageSharp/Colors/PackedPixel/Rgba1010102.cs
index 95a8d3b978..4f99feb6e5 100644
--- a/src/ImageSharp/Colors/PackedPixel/Rgba1010102.cs
+++ b/src/ImageSharp/Colors/PackedPixel/Rgba1010102.cs
@@ -39,6 +39,9 @@ namespace ImageSharp
///
public uint PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/Rgba64.cs b/src/ImageSharp/Colors/PackedPixel/Rgba64.cs
index 679a55c4e6..a23e57ec3d 100644
--- a/src/ImageSharp/Colors/PackedPixel/Rgba64.cs
+++ b/src/ImageSharp/Colors/PackedPixel/Rgba64.cs
@@ -38,6 +38,9 @@ namespace ImageSharp
///
public ulong PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/Short2.cs b/src/ImageSharp/Colors/PackedPixel/Short2.cs
index 1c1cb28c34..f26e825789 100644
--- a/src/ImageSharp/Colors/PackedPixel/Short2.cs
+++ b/src/ImageSharp/Colors/PackedPixel/Short2.cs
@@ -51,6 +51,9 @@ namespace ImageSharp
///
public uint PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Colors/PackedPixel/Short4.cs b/src/ImageSharp/Colors/PackedPixel/Short4.cs
index 2c11a1f8b1..6dc7545e1b 100644
--- a/src/ImageSharp/Colors/PackedPixel/Short4.cs
+++ b/src/ImageSharp/Colors/PackedPixel/Short4.cs
@@ -53,6 +53,9 @@ namespace ImageSharp
///
public ulong PackedValue { get; set; }
+ ///
+ public BulkPixelOperations BulkOperations => new BulkPixelOperations();
+
///
/// Compares two objects for equality.
///
diff --git a/src/ImageSharp/Common/Memory/ArrayPointer.cs b/src/ImageSharp/Common/Memory/ArrayPointer.cs
new file mode 100644
index 0000000000..c864d31fd1
--- /dev/null
+++ b/src/ImageSharp/Common/Memory/ArrayPointer.cs
@@ -0,0 +1,50 @@
+namespace ImageSharp
+{
+ using System.Runtime.CompilerServices;
+
+ ///
+ /// Utility methods to
+ ///
+ internal static class ArrayPointer
+ {
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe void Copy(ArrayPointer source, ArrayPointer destination, int count)
+ where T : struct
+ {
+ Unsafe.CopyBlock((void*)source.PointerAtOffset, (void*)destination.PointerAtOffset, USizeOf(count));
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe void Copy(ArrayPointer source, ArrayPointer destination, int countInSource)
+ where T : struct
+ {
+ Unsafe.CopyBlock((void*)source.PointerAtOffset, (void*)destination.PointerAtOffset, USizeOf(countInSource));
+ }
+
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static unsafe void Copy(ArrayPointer source, ArrayPointer destination, int countInDest)
+ where T : struct
+ {
+ Unsafe.CopyBlock((void*)source.PointerAtOffset, (void*)destination.PointerAtOffset, USizeOf(countInDest));
+ }
+
+ ///
+ /// Gets the size of `count` elements in bytes.
+ ///
+ /// The count of the elements
+ /// The size in bytes as int
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static int SizeOf(int count)
+ where T : struct => Unsafe.SizeOf() * count;
+
+ ///
+ /// Gets the size of `count` elements in bytes as UInt32
+ ///
+ /// The count of the elements
+ /// The size in bytes as UInt32
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ public static uint USizeOf(int count)
+ where T : struct
+ => (uint)SizeOf(count);
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Benchmarks/General/ArrayCopy.cs b/tests/ImageSharp.Benchmarks/General/ArrayCopy.cs
index dddd83e424..72fd6dc248 100644
--- a/tests/ImageSharp.Benchmarks/General/ArrayCopy.cs
+++ b/tests/ImageSharp.Benchmarks/General/ArrayCopy.cs
@@ -2,22 +2,23 @@
// Copyright (c) James Jackson-South and contributors.
// Licensed under the Apache License, Version 2.0.
//
-
namespace ImageSharp.Benchmarks.General
{
using System;
using System.Runtime.CompilerServices;
+ using System.Runtime.InteropServices;
using BenchmarkDotNet.Attributes;
+ [Config(typeof(Config.Short))]
public class ArrayCopy
{
- [Params(100, 1000, 10000)]
+ [Params(10, 100, 1000, 10000)]
public int Count { get; set; }
- private byte[] source;
+ byte[] source;
- private byte[] destination;
+ byte[] destination;
[Setup]
public void SetUp()
@@ -42,6 +43,12 @@ namespace ImageSharp.Benchmarks.General
}
}
+ [Benchmark(Description = "Copy using Buffer.BlockCopy()")]
+ public void CopyUsingBufferBlockCopy()
+ {
+ Buffer.BlockCopy(this.source, 0, this.destination, 0, this.Count);
+ }
+
[Benchmark(Description = "Copy using Buffer.MemoryCopy")]
public unsafe void CopyUsingBufferMemoryCopy()
{
@@ -51,5 +58,15 @@ namespace ImageSharp.Benchmarks.General
Buffer.MemoryCopy(pinnedSource, pinnedDestination, this.Count, this.Count);
}
}
+
+
+ [Benchmark(Description = "Copy using Marshal.Copy")]
+ public unsafe void CopyUsingMarshalCopy()
+ {
+ fixed (byte* pinnedDestination = this.destination)
+ {
+ Marshal.Copy(this.source, 0, (IntPtr)pinnedDestination, this.Count);
+ }
+ }
}
}
diff --git a/tests/ImageSharp.Tests/Colors/BulkPixelOperationsTests.cs b/tests/ImageSharp.Tests/Colors/BulkPixelOperationsTests.cs
new file mode 100644
index 0000000000..413bd94515
--- /dev/null
+++ b/tests/ImageSharp.Tests/Colors/BulkPixelOperationsTests.cs
@@ -0,0 +1,104 @@
+namespace ImageSharp.Tests.Colors
+{
+ using System;
+
+ using Xunit;
+
+ public class BulkPixelOperationsTests
+ {
+ public class TypeParam
+ {
+ }
+
+
+ [Theory]
+ [InlineData(default(TypeParam))]
+ [InlineData(default(TypeParam))]
+ public virtual void PackFromVector4(TypeParam dummy)
+ where TColor : struct, IPixel
+ {
+ throw new NotImplementedException();
+ }
+
+ [Theory]
+ [InlineData(default(TypeParam))]
+ [InlineData(default(TypeParam))]
+ public virtual void PackToVector4(TypeParam dummy)
+ where TColor : struct, IPixel
+ {
+ throw new NotImplementedException();
+ }
+
+ [Theory]
+ [InlineData(default(TypeParam))]
+ [InlineData(default(TypeParam))]
+ public virtual void PackToXyzBytes(TypeParam dummy)
+ where TColor : struct, IPixel
+ {
+ throw new NotImplementedException();
+ }
+
+ [Theory]
+ [InlineData(default(TypeParam))]
+ [InlineData(default(TypeParam))]
+ public virtual void PackFromXyzBytes(TypeParam dummy)
+ where TColor : struct, IPixel
+ {
+ throw new NotImplementedException();
+ }
+
+ [Theory]
+ [InlineData(default(TypeParam))]
+ [InlineData(default(TypeParam))]
+ public virtual void PackToXyzwBytes(TypeParam dummy)
+ where TColor : struct, IPixel
+ {
+ throw new NotImplementedException();
+ }
+
+ [Theory]
+ [InlineData(default(TypeParam))]
+ [InlineData(default(TypeParam))]
+ public virtual void PackFromXyzwBytes(TypeParam dummy)
+ where TColor : struct, IPixel
+ {
+ throw new NotImplementedException();
+ }
+
+ [Theory]
+ [InlineData(default(TypeParam))]
+ [InlineData(default(TypeParam))]
+ public virtual void PackToZyxBytes(TypeParam dummy)
+ where TColor : struct, IPixel
+ {
+ throw new NotImplementedException();
+ }
+
+ [Theory]
+ [InlineData(default(TypeParam))]
+ [InlineData(default(TypeParam))]
+ public virtual void PackFromZyxBytes(TypeParam dummy)
+ where TColor : struct, IPixel
+ {
+ throw new NotImplementedException();
+ }
+
+ [Theory]
+ [InlineData(default(TypeParam))]
+ [InlineData(default(TypeParam))]
+ public virtual void PackToZyxwBytes(TypeParam dummy)
+ where TColor : struct, IPixel
+ {
+ throw new NotImplementedException();
+ }
+
+ [Theory]
+ [InlineData(default(TypeParam))]
+ [InlineData(default(TypeParam))]
+ public virtual void PackFromZyxwBytes(TypeParam dummy)
+ where TColor : struct, IPixel
+ {
+ throw new NotImplementedException();
+ }
+ }
+}
\ No newline at end of file
diff --git a/tests/ImageSharp.Tests/Common/ArrayPointerTests.cs b/tests/ImageSharp.Tests/Common/ArrayPointerTests.cs
index 076e2512c8..916a109475 100644
--- a/tests/ImageSharp.Tests/Common/ArrayPointerTests.cs
+++ b/tests/ImageSharp.Tests/Common/ArrayPointerTests.cs
@@ -3,6 +3,7 @@
namespace ImageSharp.Tests.Common
{
using System;
+ using System.Runtime.CompilerServices;
using Xunit;
@@ -10,18 +11,16 @@ namespace ImageSharp.Tests.Common
{
public struct Foo
{
-#pragma warning disable CS0414
- private int a;
+ public int A;
- private double b;
-#pragma warning restore CS0414
+ public double B;
internal static Foo[] CreateArray(int size)
{
Foo[] result = new Foo[size];
for (int i = 0; i < size; i++)
{
- result[i] = new Foo() { a = i, b = i };
+ result[i] = new Foo() { A = i, B = i };
}
return result;
}
@@ -79,5 +78,90 @@ namespace ImageSharp.Tests.Common
Assert.Equal((IntPtr)(p + totalOffset), ap.PointerAtOffset);
}
}
+
+ public class Copy
+ {
+ [Theory]
+ [InlineData(4)]
+ [InlineData(1500)]
+ public void GenericToOwnType(int count)
+ {
+ Foo[] source = Foo.CreateArray(count + 2);
+ Foo[] dest = new Foo[count + 5];
+
+ fixed (Foo* pSource = source)
+ fixed (Foo* pDest = dest)
+ {
+ ArrayPointer apSource = new ArrayPointer(source, pSource);
+ ArrayPointer apDest = new ArrayPointer(dest, pDest);
+
+ ArrayPointer.Copy(apSource, apDest, count);
+ }
+
+ Assert.Equal(source[0], dest[0]);
+ Assert.Equal(source[count-1], dest[count-1]);
+ Assert.NotEqual(source[count], dest[count]);
+ }
+
+ [Theory]
+ [InlineData(4)]
+ [InlineData(1500)]
+ public void GenericToBytes(int count)
+ {
+ int destCount = count * sizeof(Foo);
+ Foo[] source = Foo.CreateArray(count + 2);
+ byte[] dest = new byte[destCount + sizeof(Foo) + 1];
+
+ fixed (Foo* pSource = source)
+ fixed (byte* pDest = dest)
+ {
+ ArrayPointer apSource = new ArrayPointer(source, pSource);
+ ArrayPointer apDest = new ArrayPointer(dest, pDest);
+
+ ArrayPointer.Copy(apSource, apDest, count);
+ }
+
+ Assert.True(ElementsAreEqual(source, dest, 0));
+ Assert.True(ElementsAreEqual(source, dest, count - 1));
+ Assert.False(ElementsAreEqual(source, dest, count));
+ }
+
+ [Theory]
+ [InlineData(4)]
+ [InlineData(1500)]
+ public void BytesToGeneric(int count)
+ {
+ int destCount = count * sizeof(Foo);
+ byte[] source = new byte[destCount + sizeof(Foo) + 1];
+ Foo[] dest = Foo.CreateArray(count + 2);
+
+ fixed(byte* pSource = source)
+ fixed (Foo* pDest = dest)
+ {
+ ArrayPointer apSource = new ArrayPointer(source, pSource);
+ ArrayPointer apDest = new ArrayPointer(dest, pDest);
+
+ ArrayPointer.Copy(apSource, apDest, count);
+ }
+
+ Assert.True(ElementsAreEqual(dest, source, 0));
+ Assert.True(ElementsAreEqual(dest, source, count - 1));
+ Assert.False(ElementsAreEqual(dest, source, count));
+ }
+
+ private static bool ElementsAreEqual(Foo[] array, byte[] rawArray, int index)
+ {
+ fixed (Foo* pArray = array)
+ fixed (byte* pRaw = rawArray)
+ {
+ Foo* pCasted = (Foo*)pRaw;
+
+ Foo val1 = pArray[index];
+ Foo val2 = pCasted[index];
+
+ return val1.Equals(val2);
+ }
+ }
+ }
}
}
\ No newline at end of file