Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

chore: Ensure building delegates are static #900

Merged
merged 2 commits into from
Nov 8, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 58 additions & 0 deletions src/Uno.Extensions.Core/Option.T.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,31 @@

namespace Uno.Extensions;

/// <summary>
/// A wrapper over a optional value that describes its absence or presence.
/// </summary>
/// <typeparam name="T">The type of the value</typeparam>
public readonly struct Option<T> : IOption, IEquatable<Option<T>>
{
/// <summary>
/// Creates a new optional value that is flagged as present.
/// </summary>
/// <param name="value">The value.</param>
/// <returns>The optional value.</returns>
public static Option<T> Some(T value)
=> new(OptionType.Some, value);

/// <summary>
/// Creates a new optional value that is flagged as absent.
/// </summary>
/// <returns>The optional value.</returns>
public static Option<T> None()
=> default;

/// <summary>
/// Creates a new optional value that is flagged as neither present nor absent.
/// </summary>
/// <returns>The optional value.</returns>
public static Option<T> Undefined()
=> new(OptionType.Undefined);

Expand All @@ -25,40 +42,73 @@ internal Option(OptionType type, T? value = default)
_value = value;
}

/// <summary>
/// Gets the type of this optional value.
/// </summary>
public OptionType Type => _type;

/// <summary>
/// Gets a boolean that indicates if the <see cref="Type"/> of this optional is <see cref="OptionType.Undefined"/>.
/// </summary>
public bool IsUndefined()
=> _type is OptionType.Undefined;

/// <summary>
/// Gets a boolean that indicates if the <see cref="Type"/> of this optional is <see cref="OptionType.None"/>.
/// </summary>
public bool IsNone()
=> _type is OptionType.None;

/// <summary>
/// Gets a boolean that indicates if the <see cref="Type"/> of this optional is <see cref="OptionType.Some"/>.
/// </summary>
/// <param name="value">The value is any.</param>
public bool IsSome([NotNullWhen(true)] out T value)
{
value = _value!;
return _type is OptionType.Some;
}

/// <inheritdoc />
bool IOption.IsSome(out object? value)
{
value = _value;
return _type is OptionType.Some;
}

/// <summary>
/// Gets the value if <see cref="Type"/> is <seealso cref="OptionType.Some"/>, other returns the default(<typeparamref name="T"/>).
/// </summary>
/// <returns>The value if Some, default(T) otherwise.</returns>
public T? SomeOrDefault()
=> _value;

/// <inheritdoc />
object? IOption.SomeOrDefault()
=> _value;

/// <summary>
/// Gets the value if <see cref="Type"/> is <seealso cref="OptionType.Some"/>, other returns the <paramref name="defaultValue"/>.
/// </summary>
/// <param name="defaultValue">The default value to return is this optional value is not present.</param>
/// <returns>The value if Some, <paramref name="defaultValue"/> otherwise.</returns>
public T SomeOrDefault(T defaultValue)
=> _type is OptionType.Some
? _value!
: defaultValue;

/// <summary>
/// Creates a new optional value that is flagged as present.
/// </summary>
/// <param name="value">The value.</param>
public static implicit operator Option<T>(T value)
=> new(OptionType.Some, value);

/// <summary>
/// Gets the value of an option value if its <see cref="Type"/> is <seealso cref="OptionType.Some"/>
/// </summary>
/// <param name="option">The optional value.</param>
/// <exception cref="InvalidCastException">If the <see cref="Type"/> is not <seealso cref="OptionType.Some"/>.</exception>
public static explicit operator T(Option<T> option)
{
if (option._type is not OptionType.Some)
Expand All @@ -69,9 +119,17 @@ public static explicit operator T(Option<T> option)
return option._value!;
}

/// <summary>
/// Changes the type of an optional value.
/// </summary>
/// <param name="option">The optional value.</param>
public static explicit operator Option<object>(Option<T> option)
=> new(option._type, option._value);

/// <summary>
/// Changes the type of an optional value.
/// </summary>
/// <param name="option">The optional value.</param>
public static explicit operator Option<T>(Option<object> option)
=> new(option._type, option._value is T value ? value : default);

Expand Down
16 changes: 13 additions & 3 deletions src/Uno.Extensions.Core/OptionType.cs
Original file line number Diff line number Diff line change
@@ -1,15 +1,25 @@
#pragma warning disable CS1591 // XML Doc, will be moved elsewhere

using System;
using System;
using System.Linq;

namespace Uno.Extensions;

/// <summary>
/// Defines the possible types of an <see cref="Option{T}"/>
/// </summary>
public enum OptionType : short
{
/// <summary>
/// Indicates the absence of a value
/// </summary>
None = 0, // The default so default(Option<T>) == Option<T>.None

/// <summary>
/// Indicates the presence of a value
/// </summary>
Some = 1,

/// <summary>
/// Indicates that incertitude about the presence or the absence of a value.
/// </summary>
Undefined = -1,
}
16 changes: 8 additions & 8 deletions src/Uno.Extensions.Reactive/Core/Feed.T.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,15 +19,15 @@ public static class Feed<T> // We set the T on the class to it greatly helps typ
/// <param name="sourceProvider">The provider of the message enumerable sequence.</param>
/// <returns>A feed that encapsulate the source.</returns>
public static IFeed<T> Create(Func<CancellationToken, IAsyncEnumerable<Message<T>>> sourceProvider)
=> AttachedProperty.GetOrCreate(sourceProvider, sp => new CustomFeed<T>(sp));
=> AttachedProperty.GetOrCreate(sourceProvider, static sp => new CustomFeed<T>(sp));

/// <summary>
/// Gets or create a custom feed from a raw <see cref="IAsyncEnumerable{T}"/> sequence of <see cref="Message{T}"/>.
/// </summary>
/// <param name="sourceProvider">The provider of the message enumerable sequence.</param>
/// <returns>A feed that encapsulate the source.</returns>
public static IFeed<T> Create(Func<IAsyncEnumerable<Message<T>>> sourceProvider)
=> AttachedProperty.GetOrCreate(sourceProvider, sp => new CustomFeed<T>(_ => sp()));
=> AttachedProperty.GetOrCreate(sourceProvider, static sp => new CustomFeed<T>(_ => sp()));

/// <summary>
/// Gets or create a custom feed from an async method.
Expand All @@ -38,7 +38,7 @@ public static IFeed<T> Create(Func<IAsyncEnumerable<Message<T>>> sourceProvider)
public static IFeed<T> Async(AsyncFunc<Option<T>> valueProvider, Signal? refresh = null)
=> refresh is null
? AttachedProperty.GetOrCreate(valueProvider, vp => new AsyncFeed<T>(vp))
: AttachedProperty.GetOrCreate(refresh, valueProvider, (r, vp) => new AsyncFeed<T>(vp, r));
: AttachedProperty.GetOrCreate(refresh, valueProvider, static (r, vp) => new AsyncFeed<T>(vp, r));

/// <summary>
/// Gets or create a custom feed from an async method.
Expand All @@ -49,37 +49,37 @@ public static IFeed<T> Async(AsyncFunc<Option<T>> valueProvider, Signal? refresh
public static IFeed<T> Async(AsyncFunc<T> valueProvider, Signal? refresh = null)
=> refresh is null
? AttachedProperty.GetOrCreate(valueProvider, vp => new AsyncFeed<T>(vp))
: AttachedProperty.GetOrCreate(refresh, valueProvider, (r, vp) => new AsyncFeed<T>(vp, r));
: AttachedProperty.GetOrCreate(refresh, valueProvider, static (r, vp) => new AsyncFeed<T>(vp, r));

/// <summary>
/// Gets or create a custom feed from an async enumerable sequence of value.
/// </summary>
/// <param name="enumerableProvider">The async enumerable sequence of value of the resulting feed.</param>
/// <returns>A feed that encapsulate the source.</returns>
public static IFeed<T> AsyncEnumerable(Func<IAsyncEnumerable<Option<T>>> enumerableProvider)
=> AttachedProperty.GetOrCreate(enumerableProvider, ep => new AsyncEnumerableFeed<T>(ep));
=> AttachedProperty.GetOrCreate(enumerableProvider, static ep => new AsyncEnumerableFeed<T>(ep));

/// <summary>
/// Gets or create a custom feed from an async enumerable sequence of value.
/// </summary>
/// <param name="enumerableProvider">The async enumerable sequence of value of the resulting feed.</param>
/// <returns>A feed that encapsulate the source.</returns>
public static IFeed<T> AsyncEnumerable(Func<CancellationToken, IAsyncEnumerable<Option<T>>> enumerableProvider)
=> AttachedProperty.GetOrCreate(enumerableProvider, ep => new AsyncEnumerableFeed<T>(ep));
=> AttachedProperty.GetOrCreate(enumerableProvider, static ep => new AsyncEnumerableFeed<T>(ep));

/// <summary>
/// Gets or create a custom feed from an async enumerable sequence of value.
/// </summary>
/// <param name="enumerableProvider">The async enumerable sequence of value of the resulting feed.</param>
/// <returns>A feed that encapsulate the source.</returns>
public static IFeed<T> AsyncEnumerable(Func<IAsyncEnumerable<T>> enumerableProvider)
=> AttachedProperty.GetOrCreate(enumerableProvider, ep => new AsyncEnumerableFeed<T>(ep));
=> AttachedProperty.GetOrCreate(enumerableProvider, static ep => new AsyncEnumerableFeed<T>(ep));

/// <summary>
/// Gets or create a custom feed from an async enumerable sequence of value.
/// </summary>
/// <param name="enumerableProvider">The async enumerable sequence of value of the resulting feed.</param>
/// <returns>A feed that encapsulate the source.</returns>
public static IFeed<T> AsyncEnumerable(Func<CancellationToken, IAsyncEnumerable<T>> enumerableProvider)
=> AttachedProperty.GetOrCreate(enumerableProvider, ep => new AsyncEnumerableFeed<T>(ep));
=> AttachedProperty.GetOrCreate(enumerableProvider, static ep => new AsyncEnumerableFeed<T>(ep));
}
6 changes: 3 additions & 3 deletions src/Uno.Extensions.Reactive/Core/Feed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -65,7 +65,7 @@ public static IFeed<T> AsyncEnumerable<T>(Func<CancellationToken, IAsyncEnumerab
public static IFeed<TSource> Where<TSource>(
this IFeed<TSource> source,
Predicate<TSource> predicate)
=> AttachedProperty.GetOrCreate(source, predicate, (src, p) => new WhereFeed<TSource>(src, p));
=> AttachedProperty.GetOrCreate(source, predicate, static (src, p) => new WhereFeed<TSource>(src, p));

/// <summary>
/// Gets or create a feed that projects each value of a source feed.
Expand All @@ -78,7 +78,7 @@ public static IFeed<TSource> Where<TSource>(
public static IFeed<TResult> Select<TSource, TResult>(
this IFeed<TSource> source,
Func<TSource, TResult> selector)
=> AttachedProperty.GetOrCreate(source, selector, (src, s) => new SelectFeed<TSource, TResult>(src, s));
=> AttachedProperty.GetOrCreate(source, selector, static (src, s) => new SelectFeed<TSource, TResult>(src, s));

/// <summary>
/// Gets or create a feed that asynchronously projects each value of a source feed.
Expand All @@ -91,6 +91,6 @@ public static IFeed<TResult> Select<TSource, TResult>(
public static IFeed<TResult> SelectAsync<TSource, TResult>(
this IFeed<TSource> source,
AsyncFunc<TSource, TResult> selector)
=> AttachedProperty.GetOrCreate(source, selector, (src, s) => new SelectAsyncFeed<TSource, TResult>(src, s));
=> AttachedProperty.GetOrCreate(source, selector, static (src, s) => new SelectAsyncFeed<TSource, TResult>(src, s));
#endregion
}
4 changes: 2 additions & 2 deletions src/Uno.Extensions.Reactive/Core/ListFeed.T.cs
Original file line number Diff line number Diff line change
Expand Up @@ -74,13 +74,13 @@ public static IListFeed<T> AsyncEnumerable(Func<IAsyncEnumerable<IImmutableList<
/// <param name="getPage">The async method to load a page of items.</param>
/// <returns>A paginated list feed.</returns>
public static IListFeed<T> AsyncPaginatedByCursor<TCursor>(TCursor firstPage, GetPage<TCursor, T> getPage)
=> AttachedProperty.GetOrCreate(getPage.Target ?? getPage.Method, (firstPage, getPage), (_, args) => new PaginatedListFeed<TCursor,T>(args.firstPage, args.getPage));
=> AttachedProperty.GetOrCreate(getPage.Target ?? getPage.Method, (firstPage, getPage), static (_, args) => new PaginatedListFeed<TCursor,T>(args.firstPage, args.getPage));

/// <summary>
/// Creates a list feed for a paginated collection.
/// </summary>
/// <param name="getPage">The async method to load a page of items.</param>
/// <returns>A paginated list feed.</returns>
public static IListFeed<T> AsyncPaginated(AsyncFunc<PageRequest, IImmutableList<T>> getPage)
=> AttachedProperty.GetOrCreate(getPage, gp => new PaginatedListFeed<ByIndexCursor<T>, T>(ByIndexCursor<T>.First, ByIndexCursor<T>.GetPage(gp)));
=> AttachedProperty.GetOrCreate(getPage, static gp => new PaginatedListFeed<ByIndexCursor<T>, T>(ByIndexCursor<T>.First, ByIndexCursor<T>.GetPage(gp)));
}
2 changes: 1 addition & 1 deletion src/Uno.Extensions.Reactive/Core/ListFeed.cs
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ public static IListFeed<T> AsyncPaginated<T>(AsyncFunc<PageRequest, IImmutableLi
public static IListFeed<TSource> Where<TSource>(
this IListFeed<TSource> source,
Predicate<TSource> predicate)
=> AttachedProperty.GetOrCreate(source, predicate, (src, p) => new WhereListFeed<TSource>(src, p));
=> AttachedProperty.GetOrCreate(source, predicate, static (src, p) => new WhereListFeed<TSource>(src, p));

//public static IListFeed<TResult> Select<TSource, TResult>(
// this IListFeed<TSource> source,
Expand Down
Loading