/// <summary> /// Parses a <see cref="ulong"/> from the specified <see cref="ReadOnlyBuffer"/> /// </summary> /// <param name="buffer">The <see cref="ReadOnlyBuffer"/> to parse</param> public static ulong GetUInt64(this ReadOnlyBuffer buffer) { if (Utf8Parser.TryParse(buffer.First.Span, out ulong value, out _)) { return(value); } if (buffer.IsSingleSegment) // no more data to parse { throw new InvalidOperationException(); } var bufferLength = buffer.Length; int toParseLength = 21; // longest invariant UTF8 UInt64 + 1 (so we know there is a delimiter at teh end) if (bufferLength < 21) { toParseLength = (int)bufferLength; } Span <byte> toParseBuffer = stackalloc byte[toParseLength]; buffer.CopyTo(toParseBuffer); if (Utf8Parser.TryParse(toParseBuffer, out value, out _)) { return(value); } throw new InvalidOperationException(); }
/// <summary> /// Decodes the utf8 encoded bytes in the <see cref="ReadOnlyBuffer"/> into a <see cref="string"/> /// </summary> /// <param name="buffer">The buffer to decode</param> public static string GetUtf8Span(this ReadOnlyBuffer buffer) { if (buffer.IsEmpty) { return(null); } // Assign 'textSpan' to something formally stack-referring. // The default classification is "returnable, not referring to stack", we want the opposite in this case. ReadOnlySpan <byte> textSpan = stackalloc byte[0]; if (buffer.IsSingleSegment) { textSpan = buffer.First.Span; } else if (buffer.Length < 128) // REVIEW: What's a good number { Span <byte> destination = stackalloc byte[128]; buffer.CopyTo(destination); // We are able to cast because buffer.Length < 128 textSpan = destination.Slice(0, (int)buffer.Length); } else { // Heap allocated copy to parse into array (should be rare) textSpan = new ReadOnlySpan <byte>(buffer.ToArray()); } return(new Utf8Span(textSpan).ToString()); }
public static void CopyToSpan() { int[] src = { 1, 2, 3 }; int[] dst = { 99, 100, 101 }; var srcBuffer = new ReadOnlyBuffer <int>(src); srcBuffer.CopyTo(dst.AsSpan()); Assert.Equal <int>(src, dst); }
public void Allocate_ReadBackBuffer_Copy_Range(Device device, int destinationOffset, int bufferOffset, int count) { int[] source = new int[4096]; new Random(42).NextBytes(source.AsSpan().AsBytes()); using ReadOnlyBuffer <int> readOnlyBuffer = device.Get().AllocateReadOnlyBuffer(source); using ReadBackBuffer <int> readBackBuffer = device.Get().AllocateReadBackBuffer <int>(readOnlyBuffer.Length); readOnlyBuffer.CopyTo(readBackBuffer, destinationOffset, bufferOffset, count); Assert.AreEqual(source.Length, readBackBuffer.Length); Assert.IsTrue(source.AsSpan(bufferOffset, count).SequenceEqual(readBackBuffer.Span.Slice(destinationOffset, count))); }
public void Allocate_ReadBackBuffer_Copy_Full(Device device) { int[] source = new int[4096]; new Random(42).NextBytes(source.AsSpan().AsBytes()); using ReadOnlyBuffer <int> readOnlyBuffer = device.Get().AllocateReadOnlyBuffer(source); using ReadBackBuffer <int> readBackBuffer = device.Get().AllocateReadBackBuffer <int>(readOnlyBuffer.Length); readOnlyBuffer.CopyTo(readBackBuffer); Assert.AreEqual(source.Length, readBackBuffer.Length); Assert.IsTrue(source.AsSpan().SequenceEqual(readBackBuffer.Span)); }