Skip to content

Commit

Permalink
CopyValuesTo and CopyErrorsTo for Result
Browse files Browse the repository at this point in the history
  • Loading branch information
jtmueller committed May 22, 2024
1 parent d8bd839 commit 919c4a0
Show file tree
Hide file tree
Showing 4 changed files with 185 additions and 20 deletions.
4 changes: 4 additions & 0 deletions src/RustyOptions/Async/ResultAsyncExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -731,6 +731,10 @@ public static async ValueTask<Result<T, T2Err>> OrElseAsync<T, T1Err, T2Err>(thi
return Result.Ok<T, T2Err>(result.Unwrap());
}

// NOTE: Due to a bug in coverlet.collector, certain lines in methods involving IAsyncEnumerable
// will show as partially-covered in code-coverage tools, even when they are fully-covered.
// https://github.com/coverlet-coverage/coverlet/issues/1104#issuecomment-1005332269

/// <summary>
/// Flattens an asynchronous sequence of <see cref="Result{T, TErr}"/> into a sequence containing all inner values.
/// Error results are discarded.
Expand Down
15 changes: 9 additions & 6 deletions src/RustyOptions/NumericOptionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -267,8 +267,9 @@ public static IEnumerable<T> Values<T>(this IEnumerable<NumericOption<T>> self)
}

/// <summary>
/// Copies the inner values of all <see cref="NumericOption{T}"/> in a span to a <paramref name="destination"/> span,
/// returning the destination span trimmed to the number of values copied.
/// Copies the inner values of all <see cref="NumericOption{T}"/> in an array
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied.
/// </summary>
/// <typeparam name="T">The type of the numeric option values.</typeparam>
/// <param name="self">The source span of numeric options.</param>
Expand All @@ -285,8 +286,9 @@ public static Span<T> CopyValuesTo<T>(this NumericOption<T>[] self, Span<T> dest
}

/// <summary>
/// Copies the inner values of all <see cref="NumericOption{T}"/> in a span to a <paramref name="destination"/> span,
/// returning the destination span trimmed to the number of values copied.
/// Copies the inner values of all <see cref="NumericOption{T}"/> in a list
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied.
/// </summary>
/// <typeparam name="T">The type of the numeric option values.</typeparam>
/// <param name="self">The source span of numeric options.</param>
Expand All @@ -303,8 +305,9 @@ public static Span<T> CopyValuesTo<T>(this List<NumericOption<T>> self, Span<T>
}

/// <summary>
/// Copies the inner values of all <see cref="NumericOption{T}"/> in a span to a <paramref name="destination"/> span,
/// returning the destination span trimmed to the number of values copied.
/// Copies the inner values of all <see cref="NumericOption{T}"/> in a span
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied.
/// </summary>
/// <typeparam name="T">The type of the numeric option values.</typeparam>
/// <param name="self">The source span of numeric options.</param>
Expand Down
20 changes: 12 additions & 8 deletions src/RustyOptions/OptionCollectionExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,9 @@ public static IEnumerable<T> Values<T>(this IEnumerable<Option<T>> self)
}

/// <summary>
/// Copies the inner values of all <see cref="Option{T}"/> in a span to a <paramref name="destination"/> span,
/// returning the destination span trimmed to the number of values copied.
/// Copies the inner values of all <see cref="Option{T}"/> in an array
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied.
/// </summary>
/// <typeparam name="T">The type of the numeric option values.</typeparam>
/// <param name="self">The source span of numeric options.</param>
Expand All @@ -58,8 +59,9 @@ public static Span<T> CopyValuesTo<T>(this Option<T>[] self, Span<T> destination
}

/// <summary>
/// Copies the inner values of all <see cref="Option{T}"/> in a span to a <paramref name="destination"/> span,
/// returning the destination span trimmed to the number of values copied.
/// Copies the inner values of all <see cref="Option{T}"/> in a List
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied.
/// </summary>
/// <typeparam name="T">The type of the numeric option values.</typeparam>
/// <param name="self">The source span of numeric options.</param>
Expand All @@ -76,8 +78,9 @@ public static Span<T> CopyValuesTo<T>(this List<Option<T>> self, Span<T> destina
}

/// <summary>
/// Copies the inner values of all <see cref="Option{T}"/> in a span to a <paramref name="destination"/> span,
/// returning the destination span trimmed to the number of values copied.
/// Copies the inner values of all <see cref="Option{T}"/> in a span
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied.
/// </summary>
/// <typeparam name="T">The type of the numeric option values.</typeparam>
/// <param name="self">The source span of numeric options.</param>
Expand All @@ -94,8 +97,9 @@ public static Span<T> CopyValuesTo<T>(this Span<Option<T>> self, Span<T> destina
}

/// <summary>
/// Copies the inner values of all <see cref="Option{T}"/> in a span to a <paramref name="destination"/> span,
/// returning the destination span trimmed to the number of values copied.
/// Copies the inner values of all <see cref="Option{T}"/> in a span
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied.
/// </summary>
/// <typeparam name="T">The type of the numeric option values.</typeparam>
/// <param name="self">The source span of numeric options.</param>
Expand Down
166 changes: 160 additions & 6 deletions src/RustyOptions/ResultCollectionExtensions.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using static System.ArgumentNullException;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static System.ArgumentNullException;

namespace RustyOptions;

Expand All @@ -7,10 +9,6 @@ namespace RustyOptions;
/// </summary>
public static class ResultCollectionExtensions
{
// NOTE: Due to a bug in coverlet.collector, certain lines in methods involving IAsyncEnumerable
// will show as partially-covered in code-coverage tools, even when they are fully-covered.
// https://github.com/coverlet-coverage/coverlet/issues/1104#issuecomment-1005332269

/// <summary>
/// Flattens a sequence of <see cref="Result{T, TErr}"/> into a sequence containing all inner values.
/// Error results are discarded.
Expand All @@ -32,7 +30,84 @@ public static IEnumerable<T> Values<T, TErr>(this IEnumerable<Result<T, TErr>> s
}
}

// TODO: Span overload for Values?
/// <summary>
/// Copies the inner values of all <see cref="Result{T, TErr}"/> in an array
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied. Error results are discarded.
/// </summary>
/// <param name="self">The source span of results.</param>
/// <param name="destination">The destination span to copy the values to.</param>
/// <returns>A flattened sequence of values.</returns>
/// <exception cref="System.IndexOutOfRangeException">
/// Thrown if the destination span is too small to hold all the values.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> CopyValuesTo<T, TErr>(this Result<T, TErr>[] self, Span<T> destination)
where T : notnull
{
return CopyValuesTo((ReadOnlySpan<Result<T, TErr>>)self, destination);
}

/// <summary>
/// Copies the inner values of all <see cref="Result{T, TErr}"/> in a List
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied. Error results are discarded.
/// </summary>
/// <param name="self">The source span of results.</param>
/// <param name="destination">The destination span to copy the values to.</param>
/// <returns>A flattened sequence of values.</returns>
/// <exception cref="System.IndexOutOfRangeException">
/// Thrown if the destination span is too small to hold all the values.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> CopyValuesTo<T, TErr>(this List<Result<T, TErr>> self, Span<T> destination)
where T : notnull
{
return CollectionsMarshal.AsSpan(self).CopyValuesTo(destination);
}

/// <summary>
/// Copies the inner values of all <see cref="Result{T, TErr}"/> in a span
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied. Error results are discarded.
/// </summary>
/// <param name="self">The source span of results.</param>
/// <param name="destination">The destination span to copy the values to.</param>
/// <returns>A flattened sequence of values.</returns>
/// <exception cref="System.IndexOutOfRangeException">
/// Thrown if the destination span is too small to hold all the values.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<T> CopyValuesTo<T, TErr>(this Span<Result<T, TErr>> self, Span<T> destination)
where T : notnull
{
return CopyValuesTo((ReadOnlySpan<Result<T, TErr>>)self, destination);
}

/// <summary>
/// Copies the inner values of all <see cref="Result{T, TErr}"/> in a span
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied. Error results are discarded.
/// </summary>
/// <param name="self">The source span of results.</param>
/// <param name="destination">The destination span to copy the values to.</param>
/// <returns>A flattened sequence of values.</returns>
/// <exception cref="System.IndexOutOfRangeException">
/// Thrown if the destination span is too small to hold all the values.
/// </exception>
public static Span<T> CopyValuesTo<T, TErr>(this ReadOnlySpan<Result<T, TErr>> self, Span<T> destination)
where T : notnull
{
int j = 0;
for (int i = 0; i < self.Length; i++)
{
if (self[i].IsOk(out var value))
{
destination[j++] = value;
}
}
return destination[..j];
}

/// <summary>
/// Flattens a sequence of <see cref="Result{T, TErr}"/> into a sequence containing all error values.
Expand All @@ -54,4 +129,83 @@ public static IEnumerable<TErr> Errors<T, TErr>(this IEnumerable<Result<T, TErr>
}
}
}

/// <summary>
/// Copies the error values of all <see cref="Result{T, TErr}"/> in an array
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied. Error results are discarded.
/// </summary>
/// <param name="self">The source span of results.</param>
/// <param name="destination">The destination span to copy the errors to.</param>
/// <returns>A flattened sequence of values.</returns>
/// <exception cref="System.IndexOutOfRangeException">
/// Thrown if the destination span is too small to hold all the errors.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<TErr> CopyErrorssTo<T, TErr>(this Result<T, TErr>[] self, Span<TErr> destination)
where T : notnull
{
return CopyErrorsTo((ReadOnlySpan<Result<T, TErr>>)self, destination);
}

/// <summary>
/// Copies the error values of all <see cref="Result{T, TErr}"/> in a List
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied. Error results are discarded.
/// </summary>
/// <param name="self">The source span of results.</param>
/// <param name="destination">The destination span to copy the errors to.</param>
/// <returns>A flattened sequence of values.</returns>
/// <exception cref="System.IndexOutOfRangeException">
/// Thrown if the destination span is too small to hold all the errors.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<TErr> CopyErrorsTo<T, TErr>(this List<Result<T, TErr>> self, Span<TErr> destination)
where T : notnull
{
return CollectionsMarshal.AsSpan(self).CopyErrorsTo(destination);
}

/// <summary>
/// Copies the error values of all <see cref="Result{T, TErr}"/> in a span
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied. Error results are discarded.
/// </summary>
/// <param name="self">The source span of results.</param>
/// <param name="destination">The destination span to copy the errors to.</param>
/// <returns>A flattened sequence of values.</returns>
/// <exception cref="System.IndexOutOfRangeException">
/// Thrown if the destination span is too small to hold all the errors.
/// </exception>
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static Span<TErr> CopyErrorsTo<T, TErr>(this Span<Result<T, TErr>> self, Span<TErr> destination)
where T : notnull
{
return CopyErrorsTo((ReadOnlySpan<Result<T, TErr>>)self, destination);
}

/// <summary>
/// Copies the error values of all <see cref="Result{T, TErr}"/> in a span
/// to a <paramref name="destination"/> span, returning the destination span
/// trimmed to the number of values copied. Error results are discarded.
/// </summary>
/// <param name="self">The source span of results.</param>
/// <param name="destination">The destination span to copy the errors to.</param>
/// <returns>A flattened sequence of values.</returns>
/// <exception cref="System.IndexOutOfRangeException">
/// Thrown if the destination span is too small to hold all the errors.
/// </exception>
public static Span<TErr> CopyErrorsTo<T, TErr>(this ReadOnlySpan<Result<T, TErr>> self, Span<TErr> destination)
where T : notnull
{
int j = 0;
for (int i = 0; i < self.Length; i++)
{
if (self[i].IsErr(out var err) && err is not null)
{
destination[j++] = err;
}
}
return destination[..j];
}
}

0 comments on commit 919c4a0

Please sign in to comment.