Skip to content
This repository was archived by the owner on Jan 23, 2023. It is now read-only.

Add GetReference and TryGetArray to MemoryMarshal #15417

Merged
merged 4 commits into from
Dec 8, 2017
Merged
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Next Next commit
Add GetReference and TryGetArray to MemoryMarshal
ahsonkhan committed Dec 7, 2017
commit f6ad03c772831d4358912f424b6f7e54571058f8
2 changes: 1 addition & 1 deletion src/mscorlib/shared/System/ReadOnlyMemory.cs
Original file line number Diff line number Diff line change
@@ -29,7 +29,7 @@ public readonly struct ReadOnlyMemory<T>
private readonly int _index;
private readonly int _length;

private const int RemoveOwnedFlagBitMask = 0x7FFFFFFF;
internal const int RemoveOwnedFlagBitMask = 0x7FFFFFFF;

/// <summary>
/// Creates a new memory over the entirety of the target array.
3 changes: 3 additions & 0 deletions src/mscorlib/shared/System/ReadOnlySpan.cs
Original file line number Diff line number Diff line change
@@ -322,6 +322,9 @@ public T[] ToArray()
/// </summary>
public static ReadOnlySpan<T> Empty => default(ReadOnlySpan<T>);

// This exposes the internal representation for Span-related apis use only.
internal ByReference<T> Pointer => _pointer;

/// <summary>Gets an enumerator for this span.</summary>
public Enumerator GetEnumerator() => new Enumerator(this);

Original file line number Diff line number Diff line change
@@ -2,6 +2,7 @@
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.

using System.Buffers;
using System.Runtime.CompilerServices;

namespace System.Runtime.InteropServices
@@ -23,5 +24,36 @@ public static class MemoryMarshal
/// </remarks>
public static Memory<T> AsMemory<T>(ReadOnlyMemory<T> readOnlyMemory) =>
Unsafe.As<ReadOnlyMemory<T>, Memory<T>>(ref readOnlyMemory);

public static ref T GetReference<T>(in Span<T> span)
{
return ref span.Pointer.Value;
}

public static ref readonly T GetReference<T>(in ReadOnlySpan<T> span)
{
return ref span.Pointer.Value;
}

public static bool TryGetArray<T>(ReadOnlyMemory<T> readOnlyMemory, out ArraySegment<T> arraySegment)
{
object obj = readOnlyMemory.GetObjectStartLength(out int index, out int length);
if (index < 0)
{
if (((OwnedMemory<T>)obj).TryGetArray(out var segment))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can this be just return (((OwnedMemory<T>)obj).TryGetArray(out var arraySegment) ?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see - you need to add the local index.

{
arraySegment = new ArraySegment<T>(segment.Array, segment.Offset + (index & ReadOnlyMemory<T>.RemoveOwnedFlagBitMask), length);
return true;
}
}
else if (obj is T[] arr)
{
arraySegment = new ArraySegment<T>(arr, index, length);
return true;
}

arraySegment = default;
return false;
}
}
}
3 changes: 3 additions & 0 deletions src/mscorlib/shared/System/Span.cs
Original file line number Diff line number Diff line change
@@ -409,6 +409,9 @@ public T[] ToArray()
/// </summary>
public static Span<T> Empty => default(Span<T>);

// This exposes the internal representation for Span-related apis use only.
internal ByReference<T> Pointer => _pointer;
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should return ref T. ByReference<T> should be used only for the fields.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is that?

Wouldn't this make the implementation, essentially a duplicate, but internal, version of DangerousGetPinnableReference?

i.e.

internal ref T Reference => ref _pointer.Value;

Do we then just return Reference from MemoryMarshal.GetReference()?


/// <summary>Gets an enumerator for this span.</summary>
public Enumerator GetEnumerator() => new Enumerator(this);