Skip to content

Commit fabeba6

Browse files
committed
Added implicit ReadOnlyRefEnumerable operator
1 parent ffc95e6 commit fabeba6

File tree

2 files changed

+52
-6
lines changed

2 files changed

+52
-6
lines changed

Microsoft.Toolkit.HighPerformance/Enumerables/ReadOnlyRefEnumerable{T}.cs

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,20 @@ public ref struct ReadOnlyRefEnumerable<T>
5959
private int position;
6060

6161
#if SPAN_RUNTIME_SUPPORT
62+
/// <summary>
63+
/// Initializes a new instance of the <see cref="ReadOnlyRefEnumerable{T}"/> struct.
64+
/// </summary>
65+
/// <param name="span">The <see cref="ReadOnlySpan{T}"/> instance pointing to the first item in the target memory area.</param>
66+
/// <param name="step">The distance between items in the sequence to enumerate.</param>
67+
/// <param name="position">The current position in the sequence.</param>
68+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
69+
private ReadOnlyRefEnumerable(ReadOnlySpan<T> span, int step, int position)
70+
{
71+
this.span = span;
72+
this.step = step;
73+
this.position = position;
74+
}
75+
6276
/// <summary>
6377
/// Initializes a new instance of the <see cref="ReadOnlyRefEnumerable{T}"/> struct.
6478
/// </summary>
@@ -73,6 +87,24 @@ internal ReadOnlyRefEnumerable(in T reference, int length, int step)
7387
this.position = -1;
7488
}
7589
#else
90+
/// <summary>
91+
/// Initializes a new instance of the <see cref="ReadOnlyRefEnumerable{T}"/> struct.
92+
/// </summary>
93+
/// <param name="instance">The target <see cref="object"/> instance.</param>
94+
/// <param name="offset">The initial offset within <see paramref="instance"/>.</param>
95+
/// <param name="length">The number of items in the sequence.</param>
96+
/// <param name="step">The distance between items in the sequence to enumerate.</param>
97+
/// <param name="position">The current position in the sequence.</param>
98+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
99+
private ReadOnlyRefEnumerable(object? instance, IntPtr offset, int length, int step, int position)
100+
{
101+
this.instance = instance;
102+
this.offset = offset;
103+
this.length = length;
104+
this.step = step;
105+
this.position = position;
106+
}
107+
76108
/// <summary>
77109
/// Initializes a new instance of the <see cref="ReadOnlyRefEnumerable{T}"/> struct.
78110
/// </summary>
@@ -204,6 +236,20 @@ public readonly T[] ToArray()
204236
return array;
205237
}
206238

239+
/// <summary>
240+
/// Implicitly converts a <see cref="RefEnumerable{T}"/> instance into a <see cref="ReadOnlyRefEnumerable{T}"/> one.
241+
/// </summary>
242+
/// <param name="enumerable">The input <see cref="RefEnumerable{T}"/> instance.</param>
243+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
244+
public static implicit operator ReadOnlyRefEnumerable<T>(RefEnumerable<T> enumerable)
245+
{
246+
#if SPAN_RUNTIME_SUPPORT
247+
return new ReadOnlyRefEnumerable<T>(enumerable.Span, enumerable.Step, enumerable.Position);
248+
#else
249+
return new ReadOnlyRefEnumerable<T>(enumerable.Instance, enumerable.Offset, enumerable.Length, enumerable.Position);
250+
#endif
251+
}
252+
207253
/// <summary>
208254
/// Throws an <see cref="ArgumentException"/> when the target span is too short.
209255
/// </summary>

Microsoft.Toolkit.HighPerformance/Enumerables/RefEnumerable{T}.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public ref struct RefEnumerable<T>
5656
/// <summary>
5757
/// The current position in the sequence.
5858
/// </summary>
59-
private int position;
59+
internal int Position;
6060

6161
#if SPAN_RUNTIME_SUPPORT
6262
/// <summary>
@@ -71,7 +71,7 @@ internal RefEnumerable(ref T reference, int length, int step)
7171
Span = MemoryMarshal.CreateSpan(ref reference, length);
7272
Step = step;
7373

74-
this.position = -1;
74+
this.Position = -1;
7575
}
7676
#else
7777
/// <summary>
@@ -89,7 +89,7 @@ internal RefEnumerable(object? instance, IntPtr offset, int length, int step)
8989
Length = length;
9090
Step = step;
9191

92-
this.position = -1;
92+
this.Position = -1;
9393
}
9494
#endif
9595

@@ -103,9 +103,9 @@ internal RefEnumerable(object? instance, IntPtr offset, int length, int step)
103103
public bool MoveNext()
104104
{
105105
#if SPAN_RUNTIME_SUPPORT
106-
return ++this.position < this.Span.Length;
106+
return ++this.Position < this.Span.Length;
107107
#else
108-
return ++this.position < this.Length;
108+
return ++this.Position < this.Length;
109109
#endif
110110
}
111111

@@ -127,7 +127,7 @@ public readonly ref T Current
127127
// being inspected. We can perform all the indexing operations in this type as nint,
128128
// as the maximum offset is guaranteed never to exceed the maximum value, since on
129129
// 32 bit architectures it's not possible to allocate that much memory anyway.
130-
nint offset = (nint)(uint)this.position * (nint)(uint)this.Step;
130+
nint offset = (nint)(uint)this.Position * (nint)(uint)this.Step;
131131
ref T ri = ref Unsafe.Add(ref r0, offset);
132132

133133
return ref ri;

0 commit comments

Comments
 (0)