//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// CommonHelpers satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#nullable enable
using System;

#if !WASM
namespace CommonHelpers {
#else
namespace CommonHelpers.WASM {
#endif

//**************************************************************************************************
public static partial class HNullable {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

[HOptionalResult]
public static object? ToObject<T>(T? value)
where T: struct =>
   value.HasValue ? (object)value.Value : null;

//==================================================================================================

public static T? DefaultValueAsNull<T>(T value)
where T: struct =>
   HOps.IsDefaultValue( value ) ? (T?)null : value;

public static T NullAsDefaultValue<T>(T? value)
where T: struct =>
   value.HasValue ? value.Value : default(T);

//--------------------------------------------------------------------------------------------------

public static T? NonPositiveAsNull<T>(T value)
where T: struct,IComparable =>
   value.CompareTo( 0 ) > 0 ? value : (T?)null;

//==================================================================================================

public static int? ZeroAsNull(int value) =>
   value!=0 ? value : (int?)null;
public static long? ZeroAsNull(long value) =>
   value!=0 ? value : (long?)null;
public static short? ZeroAsNull(short value) =>
   value!=0 ? value : (short?)null;
[CLSCompliant(false)]
public static sbyte? ZeroAsNull(sbyte value) =>
   value!=0 ? value : (sbyte?)null;

[CLSCompliant(false)]
public static uint? ZeroAsNull(uint value) =>
   value!=0 ? value : (uint?)null;
[CLSCompliant(false)]
public static ulong? ZeroAsNull(ulong value) =>
   value!=0 ? value : (ulong?)null;
[CLSCompliant(false)]
public static ushort? ZeroAsNull(ushort value) =>
   value!=0 ? value : (ushort?)null;
public static byte? ZeroAsNull(byte value) =>
   value!=0 ? value : (byte?)null;

//--------------------------------------------------------------------------------------------------

public static int NullAsZero(int? value) =>
   value.HasValue ? value.Value : 0;
public static long NullAsZero(long? value) =>
   value.HasValue ? value.Value : 0;
public static short NullAsZero(short? value) =>
   value.HasValue ? value.Value : (short)0;
[CLSCompliant(false)]
public static sbyte NullAsZero(sbyte? value) =>
   value.HasValue ? value.Value : (sbyte)0;

[CLSCompliant(false)]
public static uint NullAsZero(uint? value) =>
   value.HasValue ? value.Value : 0;
[CLSCompliant(false)]
public static ulong NullAsZero(ulong? value) =>
   value.HasValue ? value.Value : 0;
[CLSCompliant(false)]
public static ushort NullAsZero(ushort? value) =>
   value.HasValue ? value.Value : (ushort)0;
public static byte NullAsZero(byte? value) =>
   value.HasValue ? value.Value : (byte)0;

//==================================================================================================

public static int? NegativeAsNull(int value) =>
   value>=0 ? value : (int?)null;
public static long? NegativeAsNull(long value) =>
   value>=0 ? value : (long?)null;
public static short? NegativeAsNull(short value) =>
   value>=0 ? value : (short?)null;
[CLSCompliant(false)]
public static sbyte? NegativeAsNull(sbyte value) =>
   value>=0 ? value : (sbyte?)null;

//--------------------------------------------------------------------------------------------------

public static int NullAsMinusOne(int? value) =>
   value.HasValue ? value.Value : -1;
public static long NullAsMinusOne(long? value) =>
   value.HasValue ? value.Value : -1;
public static short NullAsMinusOne(short? value) =>
   value.HasValue ? value.Value : (short)-1;
[CLSCompliant(false)]
public static sbyte NullAsMinusOne(sbyte? value) =>
   value.HasValue ? value.Value : (sbyte)-1;

//==================================================================================================

public static int? NonPositiveAsNull(int value) =>
   value>0 ? value : (int?)null;
public static long? NonPositiveAsNull(long value) =>
   value>0 ? value : (long?)null;
public static short? NonPositiveAsNull(short value) =>
   value>0 ? value : (short?)null;
[CLSCompliant(false)]
public static sbyte? NonPositiveAsNull(sbyte value) =>
   value>0 ? value : (sbyte?)null;

//==================================================================================================

public static T IsNullSubstitution<T>(T? value,T subst)
where T: struct =>
   value.HasValue ? value.Value : subst;

public static T SubstituteIfNull<T>(ref T? operand,T subst)
where T: struct =>
   operand.HasValue ? operand.Value : (operand=subst).Value;

//--------------------------------------------------------------------------------------------------

public static T? IsNullSubstitution<T>(T? value,T? subst)
where T: struct =>
   value.HasValue ? value : subst;

public static T? SubstituteIfNull<T>(ref T? operand,T? subst)
where T: struct =>
   operand.HasValue ? operand : operand=subst;

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // HNullable
//**************************************************************************************************

} // CommonHelpers (.WASM)
