diff --git a/src/Roaring.Net/CRoaring/FrozenRoaring32Bitmap.cs b/src/Roaring.Net/CRoaring/FrozenRoaring32Bitmap.cs
index ceef602..e067940 100644
--- a/src/Roaring.Net/CRoaring/FrozenRoaring32Bitmap.cs
+++ b/src/Roaring.Net/CRoaring/FrozenRoaring32Bitmap.cs
@@ -336,6 +336,20 @@ public bool ContainsBulk(BulkContext context, uint value)
/// Thrown when the size is too small to write the bitmap.
public void CopyTo(uint[] buffer) => _bitmap.CopyTo(buffer);
+ ///
+ /// Writes current bitmap to the given in the parameter.
+ ///
+ /// The in which the bitmap will be written.
+ /// Thrown when the size is too small to write the bitmap.
+ public void CopyTo(Memory buffer) => _bitmap.CopyTo(buffer);
+
+ ///
+ /// Writes current bitmap to the given in the parameter.
+ ///
+ /// The in which the bitmap will be written.
+ /// Thrown when the size is too small to write the bitmap.
+ public void CopyTo(Span buffer) => _bitmap.CopyTo(buffer);
+
///
/// Gets enumerator that returns the values contained in the bitmap.
///
diff --git a/src/Roaring.Net/CRoaring/IReadOnlyRoaring32Bitmap.cs b/src/Roaring.Net/CRoaring/IReadOnlyRoaring32Bitmap.cs
index 9203442..290f3dc 100644
--- a/src/Roaring.Net/CRoaring/IReadOnlyRoaring32Bitmap.cs
+++ b/src/Roaring.Net/CRoaring/IReadOnlyRoaring32Bitmap.cs
@@ -77,6 +77,10 @@ internal interface IReadOnlyRoaring32Bitmap : IDisposable
void CopyTo(uint[] buffer);
+ void CopyTo(Memory buffer);
+
+ void CopyTo(Span buffer);
+
IEnumerable Values { get; }
uint[] ToArray();
diff --git a/src/Roaring.Net/CRoaring/NativeMethods.cs b/src/Roaring.Net/CRoaring/NativeMethods.cs
index 9bb461f..2c86e83 100644
--- a/src/Roaring.Net/CRoaring/NativeMethods.cs
+++ b/src/Roaring.Net/CRoaring/NativeMethods.cs
@@ -535,6 +535,14 @@ internal static unsafe partial class NativeMethods
public static extern void roaring_bitmap_to_uint32_array(IntPtr bitmap, [Out] uint[] values);
#endif
+#if NET7_0_OR_GREATER
+ [LibraryImport("roaring", EntryPoint = "roaring_bitmap_to_uint32_array")]
+ public static partial void roaring_bitmap_to_uint32_array(IntPtr bitmap, Span values);
+#else
+ [DllImport("roaring")]
+ public static extern void roaring_bitmap_to_uint32_array(IntPtr bitmap, Span values);
+#endif
+
#if NET7_0_OR_GREATER
[LibraryImport("roaring", EntryPoint = "roaring_bitmap_serialize")]
public static partial nuint roaring_bitmap_serialize(IntPtr bitmap, [Out] byte[] buffer);
diff --git a/src/Roaring.Net/CRoaring/Roaring32Bitmap.cs b/src/Roaring.Net/CRoaring/Roaring32Bitmap.cs
index 9364495..25fb849 100644
--- a/src/Roaring.Net/CRoaring/Roaring32Bitmap.cs
+++ b/src/Roaring.Net/CRoaring/Roaring32Bitmap.cs
@@ -846,6 +846,28 @@ public void CopyTo(uint[] buffer)
NativeMethods.roaring_bitmap_to_uint32_array(Pointer, buffer);
}
+ ///
+ /// Writes current bitmap to the given in the parameter.
+ ///
+ /// The in which the bitmap will be written.
+ /// Thrown when the size is too small to write the bitmap.
+ public void CopyTo(Memory buffer) => CopyTo(buffer.Span);
+
+ ///
+ /// Writes current bitmap to the given in the parameter.
+ ///
+ /// The in which the bitmap will be written.
+ /// Thrown when the size is too small to write the bitmap.
+ public void CopyTo(Span buffer)
+ {
+ if ((ulong)buffer.Length < Count)
+ {
+ throw new ArgumentOutOfRangeException(nameof(buffer), buffer.Length, ExceptionMessages.BufferSizeIsTooSmall);
+ }
+
+ NativeMethods.roaring_bitmap_to_uint32_array(Pointer, buffer);
+ }
+
///
/// Gets enumerator that returns the values contained in the bitmap.
///
diff --git a/test/Roaring.Net.Tests/CRoaring/Roaring32BitmapTests/CollectionTests.cs b/test/Roaring.Net.Tests/CRoaring/Roaring32BitmapTests/CollectionTests.cs
index 296bcb9..0da7897 100644
--- a/test/Roaring.Net.Tests/CRoaring/Roaring32BitmapTests/CollectionTests.cs
+++ b/test/Roaring.Net.Tests/CRoaring/Roaring32BitmapTests/CollectionTests.cs
@@ -24,7 +24,7 @@ public void ToArray_Always_ReturnsArrayWithExpectedValues(uint[] expected, IRoar
}
}
- public class CopyTo
+ public class CopyToArray
{
[Theory]
[InlineTestObject(new uint[] { })]
@@ -91,6 +91,140 @@ public void CopyTo_OutputCollectionSizeGreaterThanNumberOfValues_ReturnsFilledCo
}
}
+ public class CopyToMemory
+ {
+ [Theory]
+ [InlineTestObject(new uint[] { })]
+ [InlineTestObject(new uint[] { uint.MaxValue })]
+ [InlineTestObject(new uint[] { 0, 1, 2, 3, 4 })]
+ public void CopyTo_OutputCollectionSizeEqualToNumberOfValues_ReturnsFilledCollection(uint[] expected, IRoaring32BitmapTestObjectFactory factory)
+ {
+ // Arrange
+ using IRoaring32BitmapTestObject testObject = factory.GetFromValues(expected);
+ uint[] actual = new uint[expected.Length];
+
+ // Act
+ testObject.ReadOnlyBitmap.CopyTo(actual.AsMemory());
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory]
+ [InlineTestObject]
+ public void CopyTo_OutputCollectionIsEmptyWhenBitmapHasValues_ThrowsArgumentOutOfRangeException(IRoaring32BitmapTestObjectFactory factory)
+ {
+ // Arrange
+ using IRoaring32BitmapTestObject testObject = factory.GetDefault();
+ uint[] actual = [];
+
+ // Act && Assert
+ Assert.Throws(() =>
+ {
+ testObject.ReadOnlyBitmap.CopyTo(actual.AsMemory());
+ });
+ }
+
+ [Theory]
+ [InlineTestObject]
+ public void CopyTo_OutputCollectionSizeLowerThanNumberOfValues_ThrowsArgumentOutOfRangeException(IRoaring32BitmapTestObjectFactory factory)
+ {
+ // Arrange
+ var input = new uint[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ using IRoaring32BitmapTestObject testObject = factory.GetFromValues(input);
+
+ // Act && Assert
+ Assert.Throws(() =>
+ {
+ testObject.ReadOnlyBitmap.CopyTo(new uint[input.Length - 5].AsMemory());
+ });
+ }
+
+ [Theory]
+ [InlineTestObject]
+ public void CopyTo_OutputCollectionSizeGreaterThanNumberOfValues_ReturnsFilledCollectionFromBeginning(IRoaring32BitmapTestObjectFactory factory)
+ {
+ // Arrange
+ var expected = new uint[] { 0, 1, 2, 3, 4, 0, 0, 0, 0, 0 };
+ var input = expected[..5];
+ using IRoaring32BitmapTestObject testObject = factory.GetFromValues(input);
+ uint[] actual = new uint[input.Length + 5];
+
+ // Act
+ testObject.ReadOnlyBitmap.CopyTo(actual.AsMemory());
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+ }
+
+ public class CopyToSpan
+ {
+ [Theory]
+ [InlineTestObject(new uint[] { })]
+ [InlineTestObject(new uint[] { uint.MaxValue })]
+ [InlineTestObject(new uint[] { 0, 1, 2, 3, 4 })]
+ public void CopyTo_OutputCollectionSizeEqualToNumberOfValues_ReturnsFilledCollection(uint[] expected, IRoaring32BitmapTestObjectFactory factory)
+ {
+ // Arrange
+ using IRoaring32BitmapTestObject testObject = factory.GetFromValues(expected);
+ uint[] actual = new uint[expected.Length];
+
+ // Act
+ testObject.ReadOnlyBitmap.CopyTo(actual.AsSpan());
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+
+ [Theory]
+ [InlineTestObject]
+ public void CopyTo_OutputCollectionIsEmptyWhenBitmapHasValues_ThrowsArgumentOutOfRangeException(IRoaring32BitmapTestObjectFactory factory)
+ {
+ // Arrange
+ using IRoaring32BitmapTestObject testObject = factory.GetDefault();
+ uint[] actual = [];
+
+ // Act && Assert
+ Assert.Throws(() =>
+ {
+ testObject.ReadOnlyBitmap.CopyTo(actual.AsSpan());
+ });
+ }
+
+ [Theory]
+ [InlineTestObject]
+ public void CopyTo_OutputCollectionSizeLowerThanNumberOfValues_ThrowsArgumentOutOfRangeException(IRoaring32BitmapTestObjectFactory factory)
+ {
+ // Arrange
+ var input = new uint[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
+ using IRoaring32BitmapTestObject testObject = factory.GetFromValues(input);
+
+ // Act && Assert
+ Assert.Throws(() =>
+ {
+ testObject.ReadOnlyBitmap.CopyTo(new uint[input.Length - 5].AsSpan());
+ });
+ }
+
+ [Theory]
+ [InlineTestObject]
+ public void CopyTo_OutputCollectionSizeGreaterThanNumberOfValues_ReturnsFilledCollectionFromBeginning(IRoaring32BitmapTestObjectFactory factory)
+ {
+ // Arrange
+ var expected = new uint[] { 0, 1, 2, 3, 4, 0, 0, 0, 0, 0 };
+ var input = expected[..5];
+ using IRoaring32BitmapTestObject testObject = factory.GetFromValues(input);
+ uint[] actual = new uint[input.Length + 5];
+
+ // Act
+ testObject.ReadOnlyBitmap.CopyTo(actual.AsSpan());
+
+ // Assert
+ Assert.Equal(expected, actual);
+ }
+ }
+
public class Take
{
[Theory]