//\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\
// UserRTX.NET satellite library | Author: Sergei Y.Kitáev
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
using System;

#if !WASM
namespace user_rtx { using u = user_rtx;
#else
namespace user_rtx.wasm { using u = user_rtx.wasm;
#endif

/// <summary>
/// Nullable value operations
/// </summary>
public static class nval {
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~

public static T SetValue<T>( out T? location, T value )
where T: struct
{
   location = value;
   return value;
}

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

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

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

public static T? ZeroAsNull<T>( T value )
where T: struct, IEquatable<T> =>
   !u.val.IsZero( value ) ? value : null;

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

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

public static T? ZeroAsNullB<T>( T value )
where T: struct =>
   u.val.IsZeroB( value ) ? (T?)null : value;

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

public static T? NotPositiveAsNull<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 NullAsMinus1( int? value ) =>
   value.HasValue ? value.Value : -1;
public static long NullAsMinus1( long? value ) =>
   value.HasValue ? value.Value : -1;
public static short NullAsMinus1( short? value ) =>
   value.HasValue ? value.Value : (short)-1;
[CLSCompliant(false)]
public static sbyte NullAsMinus1( sbyte? value ) =>
   value.HasValue ? value.Value : (sbyte)-1;

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

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

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
} // nval

} // user_rtx (.wasm)
