Multi-Platform Package Manager for Stable Diffusion
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

84 lines
2.6 KiB

using System;
using System.ComponentModel;
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Numerics;
using Avalonia.Data.Converters;
namespace StabilityMatrix.Avalonia.Converters;
/// <summary>
/// Converts a possibly boxed nullable value type to its default value
/// </summary>
public class NullableDefaultNumericConverter<TSource, TTarget> : IValueConverter
where TSource : unmanaged, INumber<TSource>
where TTarget : unmanaged, INumber<TTarget>
{
public ReturnBehavior NanHandling { get; set; } = ReturnBehavior.DefaultValue;
/// <summary>
/// Unboxes a nullable value type
/// </summary>
private TSource Unbox(TTarget? value)
{
if (!value.HasValue)
{
return default;
}
if (TTarget.IsNaN(value.Value))
{
return NanHandling switch
{
ReturnBehavior.DefaultValue => default,
ReturnBehavior.Throw => throw new InvalidCastException("Cannot convert NaN to a numeric type"),
_
=> throw new InvalidEnumArgumentException(
nameof(NanHandling),
(int)NanHandling,
typeof(ReturnBehavior)
)
};
}
return (TSource)System.Convert.ChangeType(value.Value, typeof(TSource));
}
/// <summary>
/// Convert a value type to a nullable value type
/// </summary>
public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (targetType != typeof(TTarget?) && !targetType.IsAssignableTo(typeof(TTarget)))
{
// ReSharper disable once LocalizableElement
throw new ArgumentException(
$"Convert Target type {targetType.Name} must be assignable to {typeof(TTarget).Name}"
);
}
return (TTarget?)System.Convert.ChangeType(value, typeof(TTarget));
}
/// <summary>
/// Convert a nullable value type to a value type
/// </summary>
public object ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
{
if (!targetType.IsAssignableTo(typeof(TSource)))
{
// ReSharper disable once LocalizableElement
throw new ArgumentException(
$"ConvertBack Target type {targetType.Name} must be assignable to {typeof(TSource).Name}"
);
}
return Unbox((TTarget?)value);
}
public enum ReturnBehavior
{
DefaultValue,
Throw
}
}