-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathMemoryMarshalExtensions.cs
More file actions
168 lines (155 loc) · 8.1 KB
/
MemoryMarshalExtensions.cs
File metadata and controls
168 lines (155 loc) · 8.1 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
using Ramstack.Collections;
using Ramstack.Text;
namespace Ramstack.InteropServices;
/// <summary>
/// Provides extension methods for the <see cref="MemoryMarshal"/> class.
/// </summary>
public static class MemoryMarshalExtensions
{
extension(MemoryMarshal)
{
/// <summary>
/// Creates a new <see cref="StringView"/> over a portion of the specified string
/// starting at a specified position to the end of the string.
/// </summary>
/// <param name="value">The string to create a view over.</param>
/// <param name="index">The zero-based starting position of the view in the string.</param>
/// <returns>
/// A <see cref="StringView"/> representing the specified portion of the string.
/// </returns>
/// <remarks>
/// This method should be used with caution as it doesn't perform argument validation.
/// The caller is responsible for ensuring:
/// <list type="bullet">
/// <item><description><paramref name="value"/> is not null.</description></item>
/// <item><description><paramref name="index"/> is within the bounds of the string.</description></item>
/// </list>
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static StringView CreateStringView(string value, int index)
{
Debug.Assert(value is not null);
Debug.Assert(value.AsSpan(index).Length == value.Length - index);
return new StringView(value, index, value.Length - index, unused: 0);
}
/// <summary>
/// Creates a new <see cref="StringView"/> over a portion of the specified string
/// starting at a specified position for a specified number of characters.
/// </summary>
/// <param name="value">The string to create a view over.</param>
/// <param name="index">The zero-based starting position of the view in the string.</param>
/// <param name="length">The number of characters to include in the view.</param>
/// <returns>
/// A <see cref="StringView"/> representing the specified portion of the string.
/// </returns>
/// <remarks>
/// This method should be used with caution as it doesn't perform argument validation.
/// The caller is responsible for ensuring:
/// <list type="bullet">
/// <item><description><paramref name="value"/> is not null.</description></item>
/// <item><description><paramref name="index"/> is within the bounds of the string.</description></item>
/// <item><description><paramref name="length"/> is valid for the specified index.</description></item>
/// </list>
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static StringView CreateStringView(string value, int index, int length)
{
Debug.Assert(value is not null);
Debug.Assert(value.AsSpan(index, length).Length == length);
return new StringView(value, index, length, unused: 0);
}
/// <summary>
/// Creates a new <see cref="ArrayView{T}"/> over a portion of the specified array,
/// starting at a specified position to the end of the array.
/// </summary>
/// <typeparam name="T">The type of elements in the array.</typeparam>
/// <param name="array">The array to create a view over.</param>
/// <param name="index">The zero-based starting position of the view in the array.</param>
/// <returns>
/// An <see cref="ArrayView{T}"/> representing the specified portion of the array.
/// </returns>
/// <remarks>
/// This method should be used with caution as it doesn't perform argument validation.
/// The caller is responsible for ensuring:
/// <list type="bullet">
/// <item><description><paramref name="array"/> is not null.</description></item>
/// <item><description><paramref name="index"/> is within the bounds of the array.</description></item>
/// </list>
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ArrayView<T> CreateArrayView<T>(T[] array, int index)
{
Debug.Assert(array is not null);
Debug.Assert(array.AsSpan(index).Length == array.Length - index);
return new ArrayView<T>(array, index, array.Length - index, unused: 0);
}
/// <summary>
/// Creates a new <see cref="ArrayView{T}"/> over a portion of the specified array
/// starting at a specified position for a specified number of elements.
/// </summary>
/// <typeparam name="T">The type of elements in the array.</typeparam>
/// <param name="array">The array to create a view over.</param>
/// <param name="index">The zero-based starting position of the view in the array.</param>
/// <param name="length">The number of elements to include in the view.</param>
/// <returns>
/// An <see cref="ArrayView{T}"/> representing the specified portion of the array.
/// </returns>
/// <remarks>
/// This method should be used with caution as it doesn't perform argument validation.
/// The caller is responsible for ensuring:
/// <list type="bullet">
/// <item><description><paramref name="array"/> is not null.</description></item>
/// <item><description><paramref name="index"/> is within the bounds of the array.</description></item>
/// <item><description><paramref name="length"/> is valid for the specified index.</description></item>
/// </list>
/// </remarks>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static ArrayView<T> CreateArrayView<T>(T[] array, int index, int length)
{
Debug.Assert(array is not null);
Debug.Assert(array.AsSpan(index, length).Length == length);
return new ArrayView<T>(array, index, length, unused: 0);
}
/// <summary>
/// Attempts to get a <see cref="StringView"/> from the underlying memory buffer.
/// </summary>
/// <param name="memory">Read-only memory containing a block of characters.</param>
/// <param name="view">When this method returns, contains the <see cref="StringView"/>
/// retrieved from the underlying read-only memory buffer.</param>
/// <returns>
/// <see langword="true"/> if the method successfully retrieves the underlying string;
/// otherwise, <see langword="false"/>.
/// </returns>
public static bool TryGetStringView(ReadOnlyMemory<char> memory, out StringView view)
{
if (MemoryMarshal.TryGetString(memory, out var value, out var start, out var length))
{
view = new StringView(value, start, length, unused: 0);
return true;
}
view = default;
return false;
}
/// <summary>
/// Attempts to get a <see cref="StringView"/> from the underlying memory buffer.
/// </summary>
/// <typeparam name="T">The type of elements in the read-only memory buffer.</typeparam>
/// <param name="memory">Read-only memory buffer.</param>
/// <param name="view">When this method returns, contains the <see cref="ArrayView{T}"/>
/// retrieved from the underlying read-only memory buffer.</param>
/// <returns>
/// <see langword="true"/> if the underlying memory buffer represents an array segment;
/// otherwise, <see langword="false"/>.
/// </returns>
public static bool TryGetArrayView<T>(ReadOnlyMemory<T> memory, out ArrayView<T> view)
{
if (MemoryMarshal.TryGetArray(memory, out var segment))
{
view = segment;
return true;
}
view = default;
return false;
}
}
}