Skip to content

Commit 1a15ee2

Browse files
committed
Added RefEnumerable<T>.CopyTo(RefEnumerable) APIs
1 parent bce507b commit 1a15ee2

File tree

2 files changed

+144
-0
lines changed

2 files changed

+144
-0
lines changed

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

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -155,6 +155,78 @@ public readonly ref readonly T Current
155155
}
156156
}
157157

158+
/// <summary>
159+
/// Copies the contents of this <see cref="ReadOnlyRefEnumerable{T}"/> into a destination <see cref="RefEnumerable{T}"/> instance.
160+
/// </summary>
161+
/// <param name="destination">The destination <see cref="RefEnumerable{T}"/> instance.</param>
162+
/// <exception cref="ArgumentException">
163+
/// Thrown when <paramref name="destination"/> is shorter than the source <see cref="ReadOnlyRefEnumerable{T}"/> instance.
164+
/// </exception>
165+
public readonly void CopyTo(RefEnumerable<T> destination)
166+
{
167+
#if SPAN_RUNTIME_SUPPORT
168+
if (this.step == 1)
169+
{
170+
destination.CopyFrom(this.span);
171+
172+
return;
173+
}
174+
175+
if (destination.Step == 1)
176+
{
177+
CopyTo(destination.Span);
178+
179+
return;
180+
}
181+
182+
ref T sourceRef = ref this.span.DangerousGetReference();
183+
ref T destinationRef = ref destination.Span.DangerousGetReference();
184+
int
185+
sourceLength = this.span.Length,
186+
destinationLength = destination.Span.Length;
187+
#else
188+
ref T sourceRef = ref RuntimeHelpers.GetObjectDataAtOffsetOrPointerReference<T>(this.instance, this.offset);
189+
ref T destinationRef = ref RuntimeHelpers.GetObjectDataAtOffsetOrPointerReference<T>(destination.Instance, destination.Offset);
190+
int
191+
sourceLength = this.length,
192+
destinationLength = destination.Length;
193+
#endif
194+
195+
if ((uint)destinationLength < (uint)sourceLength)
196+
{
197+
ThrowArgumentExceptionForDestinationTooShort();
198+
}
199+
200+
RefEnumerableHelper.CopyTo(ref sourceRef, ref destinationRef, (nint)(uint)sourceLength, (nint)(uint)this.step, (nint)(uint)destination.Step);
201+
}
202+
203+
/// <summary>
204+
/// Attempts to copy the current <see cref="ReadOnlyRefEnumerable{T}"/> instance to a destination <see cref="RefEnumerable{T}"/>.
205+
/// </summary>
206+
/// <param name="destination">The target <see cref="RefEnumerable{T}"/> of the copy operation.</param>
207+
/// <returns>Whether or not the operation was successful.</returns>
208+
public readonly bool TryCopyTo(RefEnumerable<T> destination)
209+
{
210+
#if SPAN_RUNTIME_SUPPORT
211+
int
212+
sourceLength = this.span.Length,
213+
destinationLength = destination.Span.Length;
214+
#else
215+
int
216+
sourceLength = this.length,
217+
destinationLength = destination.Length;
218+
#endif
219+
220+
if (destinationLength >= sourceLength)
221+
{
222+
CopyTo(destination);
223+
224+
return true;
225+
}
226+
227+
return false;
228+
}
229+
158230
/// <summary>
159231
/// Copies the contents of this <see cref="RefEnumerable{T}"/> into a destination <see cref="Span{T}"/> instance.
160232
/// </summary>

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

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -156,6 +156,78 @@ public readonly void Clear()
156156
RefEnumerableHelper.Clear(ref r0, (nint)(uint)length, (nint)(uint)this.Step);
157157
}
158158

159+
/// <summary>
160+
/// Copies the contents of this <see cref="RefEnumerable{T}"/> into a destination <see cref="RefEnumerable{T}"/> instance.
161+
/// </summary>
162+
/// <param name="destination">The destination <see cref="RefEnumerable{T}"/> instance.</param>
163+
/// <exception cref="ArgumentException">
164+
/// Thrown when <paramref name="destination"/> is shorter than the source <see cref="RefEnumerable{T}"/> instance.
165+
/// </exception>
166+
public readonly void CopyTo(RefEnumerable<T> destination)
167+
{
168+
#if SPAN_RUNTIME_SUPPORT
169+
if (this.Step == 1)
170+
{
171+
destination.CopyFrom(this.Span);
172+
173+
return;
174+
}
175+
176+
if (destination.Step == 1)
177+
{
178+
CopyTo(destination.Span);
179+
180+
return;
181+
}
182+
183+
ref T sourceRef = ref this.Span.DangerousGetReference();
184+
ref T destinationRef = ref destination.Span.DangerousGetReference();
185+
int
186+
sourceLength = this.Span.Length,
187+
destinationLength = destination.Span.Length;
188+
#else
189+
ref T sourceRef = ref RuntimeHelpers.GetObjectDataAtOffsetOrPointerReference<T>(this.Instance, this.Offset);
190+
ref T destinationRef = ref RuntimeHelpers.GetObjectDataAtOffsetOrPointerReference<T>(destination.Instance, destination.Offset);
191+
int
192+
sourceLength = this.Length,
193+
destinationLength = destination.Length;
194+
#endif
195+
196+
if ((uint)destinationLength < (uint)sourceLength)
197+
{
198+
ThrowArgumentExceptionForDestinationTooShort();
199+
}
200+
201+
RefEnumerableHelper.CopyTo(ref sourceRef, ref destinationRef, (nint)(uint)sourceLength, (nint)(uint)this.Step, (nint)(uint)destination.Step);
202+
}
203+
204+
/// <summary>
205+
/// Attempts to copy the current <see cref="RefEnumerable{T}"/> instance to a destination <see cref="RefEnumerable{T}"/>.
206+
/// </summary>
207+
/// <param name="destination">The target <see cref="RefEnumerable{T}"/> of the copy operation.</param>
208+
/// <returns>Whether or not the operation was successful.</returns>
209+
public readonly bool TryCopyTo(RefEnumerable<T> destination)
210+
{
211+
#if SPAN_RUNTIME_SUPPORT
212+
int
213+
sourceLength = this.Span.Length,
214+
destinationLength = destination.Span.Length;
215+
#else
216+
int
217+
sourceLength = this.Length,
218+
destinationLength = destination.Length;
219+
#endif
220+
221+
if (destinationLength >= sourceLength)
222+
{
223+
CopyTo(destination);
224+
225+
return true;
226+
}
227+
228+
return false;
229+
}
230+
159231
/// <summary>
160232
/// Copies the contents of this <see cref="RefEnumerable{T}"/> into a destination <see cref="Span{T}"/> instance.
161233
/// </summary>

0 commit comments

Comments
 (0)