Skip to content

Commit a2ecb5f

Browse files
committed
Bug fixes, added RefEnumerable<T>.[Try]CopyFrom
1 parent 0e8a2db commit a2ecb5f

File tree

2 files changed

+68
-4
lines changed

2 files changed

+68
-4
lines changed

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,7 @@ public readonly ref readonly T Current
129129
/// </summary>
130130
/// <param name="destination">The destination <see cref="Span{T}"/> instance.</param>
131131
/// <exception cref="ArgumentException">
132-
/// Thrown when <paramref name="destination" /> is shorter than the source <see cref="RefEnumerable{T}"/> instance.
132+
/// Thrown when <paramref name="destination"/> is shorter than the source <see cref="RefEnumerable{T}"/> instance.
133133
/// </exception>
134134
public readonly void CopyTo(Span<T> destination)
135135
{
@@ -176,7 +176,7 @@ public readonly bool TryCopyTo(Span<T> destination)
176176
int length = this.length;
177177
#endif
178178

179-
if (destination.Length >= length / this.step)
179+
if (destination.Length >= length)
180180
{
181181
CopyTo(destination);
182182

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

Lines changed: 66 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -166,7 +166,7 @@ public readonly void Clear()
166166
/// </summary>
167167
/// <param name="destination">The destination <see cref="Span{T}"/> instance.</param>
168168
/// <exception cref="ArgumentException">
169-
/// Thrown when <paramref name="destination" /> is shorter than the source <see cref="RefEnumerable{T}"/> instance.
169+
/// Thrown when <paramref name="destination"/> is shorter than the source <see cref="RefEnumerable{T}"/> instance.
170170
/// </exception>
171171
public readonly void CopyTo(Span<T> destination)
172172
{
@@ -213,7 +213,7 @@ public readonly bool TryCopyTo(Span<T> destination)
213213
int length = this.length;
214214
#endif
215215

216-
if (destination.Length >= length / this.step)
216+
if (destination.Length >= length)
217217
{
218218
CopyTo(destination);
219219

@@ -223,6 +223,70 @@ public readonly bool TryCopyTo(Span<T> destination)
223223
return false;
224224
}
225225

226+
/// <summary>
227+
/// Copies the contents of a source <see cref="ReadOnlySpan{T}"/> into the current <see cref="RefEnumerable{T}"/> instance.
228+
/// </summary>
229+
/// <param name="source">The source <see cref="ReadOnlySpan{T}"/> instance.</param>
230+
/// <exception cref="ArgumentException">
231+
/// Thrown when the current <see cref="RefEnumerable{T}"/> is shorter than the source <see cref="ReadOnlySpan{T}"/> instance.
232+
/// </exception>
233+
internal readonly void CopyFrom(ReadOnlySpan<T> source)
234+
{
235+
#if SPAN_RUNTIME_SUPPORT
236+
if (this.step == 1)
237+
{
238+
source.CopyTo(this.span);
239+
240+
return;
241+
}
242+
243+
ref T destinationRef = ref this.span.DangerousGetReference();
244+
int destinationLength = this.span.Length;
245+
#else
246+
ref T destinationRef = ref RuntimeHelpers.GetObjectDataAtOffsetOrPointerReference<T>(this.instance, this.offset);
247+
int destinationLength = this.length;
248+
#endif
249+
ref T sourceRef = ref source.DangerousGetReference();
250+
int sourceLength = source.Length;
251+
252+
if ((uint)destinationLength < (uint)sourceLength)
253+
{
254+
ThrowArgumentExceptionForDestinationTooShort();
255+
}
256+
257+
nint
258+
step = (nint)(uint)this.step,
259+
offset = 0;
260+
261+
for (int i = 0; i < sourceLength; i++, offset += step)
262+
{
263+
Unsafe.Add(ref destinationRef, i) = Unsafe.Add(ref sourceRef, offset);
264+
}
265+
}
266+
267+
/// <summary>
268+
/// Attempts to copy the source <see cref="ReadOnlySpan{T}"/> into the current <see cref="RefEnumerable{T}"/> instance.
269+
/// </summary>
270+
/// <param name="source">The source <see cref="ReadOnlySpan{T}"/> instance.</param>
271+
/// <returns>Whether or not the operation was successful.</returns>
272+
public readonly bool TryCopyFrom(ReadOnlySpan<T> source)
273+
{
274+
#if SPAN_RUNTIME_SUPPORT
275+
int length = this.span.Length;
276+
#else
277+
int length = this.length;
278+
#endif
279+
280+
if (length >= source.Length)
281+
{
282+
CopyFrom(source);
283+
284+
return true;
285+
}
286+
287+
return false;
288+
}
289+
226290
/// <summary>
227291
/// Fills the elements of this <see cref="RefEnumerable{T}"/> with a specified value.
228292
/// </summary>

0 commit comments

Comments
 (0)