using System;
using System.ComponentModel;
using System.Diagnostics;
using System.Globalization;
using System.Runtime.InteropServices;
namespace Vanara.PInvoke
{
/// Managed instance of the SIZE_T type.
[StructLayout(LayoutKind.Sequential), Serializable]
[TypeConverter(typeof(SizeTTypeConverter))]
[DebuggerDisplay("{Value}")]
public struct SizeT : IEquatable, IComparable, IConvertible, IComparable
{
/// Represents the smallest possible value of . This field is constant.
public static readonly SizeT MinValue = 0;
/// Represents the zero value of . This field is constant.
public static readonly SizeT Zero = default;
private UIntPtr val;
/// Initializes a new instance of the struct.
/// The value.
public SizeT(uint value) => val = (UIntPtr)value;
/// Initializes a new instance of the struct.
/// The value.
public SizeT(ulong value) => val = new UIntPtr(value);
///
/// Represents the largest possible value of . This property is determined by the maximum bit-size of a pointer.
///
public static SizeT MaxValue => UIntPtr.Size == 8 ? ulong.MaxValue : uint.MaxValue;
/// Gets the value.
/// The value.
public ulong Value { get => val.ToUInt64(); private set => val = new UIntPtr(value); }
/// Performs an implicit conversion from to .
/// The value.
/// The result of the conversion.
public static implicit operator SizeT(int value) => value >= 0 ? new SizeT((uint)value) : throw new ArgumentOutOfRangeException();
/// Performs an implicit conversion from to .
/// The value.
/// The result of the conversion.
public static implicit operator SizeT(uint value) => new(value);
/// Performs an implicit conversion from to .
/// The value.
/// The result of the conversion.
public static implicit operator SizeT(long value) => value >= 0 ? new SizeT((ulong)value) : throw new ArgumentOutOfRangeException();
/// Performs an implicit conversion from to .
/// The value.
/// The result of the conversion.
public static implicit operator SizeT(ulong value) => new(value);
/// Performs an implicit conversion from to .
/// The value.
/// The result of the conversion.
public static implicit operator int(SizeT value) => ((IConvertible)value).ToInt32(null);
/// Performs an implicit conversion from to .
/// The value.
/// The result of the conversion.
public static implicit operator uint(SizeT value) => ((IConvertible)value).ToUInt32(null);
/// Performs an implicit conversion from to .
/// The value.
/// The result of the conversion.
public static implicit operator long(SizeT value) => ((IConvertible)value).ToInt64(null);
/// Performs an implicit conversion from to .
/// The value.
/// The result of the conversion.
public static implicit operator ulong(SizeT value) => value.Value;
/// Indicates whether two instances are not equal.
/// The first integral size to compare.
/// The second integral size to compare.
///
/// if the value of is not equal to the value of ; otherwise, .
///
public static bool operator !=(SizeT s1, SizeT s2) => !s1.Equals(s2);
/// Indicates whether a specified is less than another specified .
/// The first integral size to compare.
/// The second integral size to compare.
///
/// if the value of is less than the value of ; otherwise, .
///
public static bool operator <(SizeT s1, SizeT s2) => s1.CompareTo(s2) < 0;
/// Indicates whether a specified is less than or equal to another specified .
/// The first integral size to compare.
/// The second integral size to compare.
///
/// if the value of is less than or equal to the value of ;
/// otherwise, .
///
public static bool operator <=(SizeT s1, SizeT s2) => s1.CompareTo(s2) <= 0;
/// Indicates whether two instances are equal.
/// The first integral size to compare.
/// The second integral size to compare.
///
/// if the value of is equal to the value of ; otherwise, .
///
public static bool operator ==(SizeT s1, SizeT s2) => s1.Equals(s2);
/// Indicates whether a specified is greater than another specified .
/// The first integral size to compare.
/// The second integral size to compare.
///
/// if the value of is greater than the value of ; otherwise, .
///
public static bool operator >(SizeT s1, SizeT s2) => s1.CompareTo(s2) > 0;
/// Indicates whether a specified is greater than or equal to another specified .
/// The first integral size to compare.
/// The second integral size to compare.
///
/// if the value of is greater than or equal to the value of ;
/// otherwise, .
///
public static bool operator >=(SizeT s1, SizeT s2) => s1.CompareTo(s2) >= 0;
/// Adds two specified values.
/// The first value to add.
/// The second value to add.
/// The result of adding and .
public static SizeT operator +(SizeT s1, SizeT s2) => s1.Value + s2.Value;
/// Divides two specified values.
/// The divident.
/// The divisor.
/// The result of dividing by .
public static SizeT operator /(SizeT s1, SizeT s2) => s1.Value / s2.Value;
/// Returns the remainder resulting from dividing two specified values.
/// The divident.
/// The divisor.
/// The remainder resulting from dividing by .
public static SizeT operator %(SizeT s1, SizeT s2) => s1.Value % s2.Value;
/// Multiplies two specified values.
/// The first value to multiply.
/// The second value to multiply.
/// The result of multiplying by .
public static SizeT operator *(SizeT s1, SizeT s2) => s1.Value * s2.Value;
/// Subtracts two specified values.
/// The minuend.
/// The subtrahend.
/// The result of subtracting from .
public static SizeT operator -(SizeT s1, SizeT s2) => s1.Value - s2.Value;
/// Increments the by 1.
/// The value to increment.
/// The value of incremented by 1.
public static SizeT operator ++(SizeT s1) => s1.Value += 1;
/// Decrements the by 1.
/// The value to decrement.
/// The value of decremented by 1.
public static SizeT operator --(SizeT s1) => s1.Value += 1;
///
public int CompareTo(SizeT other) => Value.CompareTo(other.Value);
///
public override bool Equals(object obj) => obj is SizeT s ? Equals(s) : Value.Equals(obj);
///
public bool Equals(SizeT other) => Value.Equals(other.Value);
///
public override int GetHashCode() => Value.GetHashCode();
///
public TypeCode GetTypeCode() => Value.GetTypeCode();
///
public override string ToString() => Value.ToString();
///
public string ToString(IFormatProvider provider) => Value.ToString(provider);
///
int IComparable.CompareTo(object obj) => Value.CompareTo(Convert.ChangeType(obj, typeof(ulong)));
///
bool IConvertible.ToBoolean(IFormatProvider provider) => ((IConvertible)Value).ToBoolean(provider);
///
byte IConvertible.ToByte(IFormatProvider provider)
{
var ul = Value;
if (ul < (ulong)byte.MaxValue)
return (byte)ul;
if (ul is uint.MaxValue or ulong.MaxValue)
return byte.MaxValue;
throw new OverflowException();
}
///
char IConvertible.ToChar(IFormatProvider provider) => ((IConvertible)Value).ToChar(provider);
///
DateTime IConvertible.ToDateTime(IFormatProvider provider) => ((IConvertible)Value).ToDateTime(provider);
///
decimal IConvertible.ToDecimal(IFormatProvider provider)
{
var ul = Value;
if (ul < decimal.MaxValue)
return (decimal)ul;
if (ul is uint.MaxValue or ulong.MaxValue)
return decimal.MaxValue;
throw new OverflowException();
}
///
double IConvertible.ToDouble(IFormatProvider provider)
{
var ul = Value;
if (ul < double.MaxValue)
return ul;
if (ul is uint.MaxValue or ulong.MaxValue)
return double.MaxValue;
throw new OverflowException();
}
///
short IConvertible.ToInt16(IFormatProvider provider)
{
var ul = Value;
if (ul < (ulong)short.MaxValue)
return (short)ul;
if (ul is uint.MaxValue or ulong.MaxValue)
return short.MaxValue;
throw new OverflowException();
}
///
int IConvertible.ToInt32(IFormatProvider provider)
{
var ul = Value;
if (ul < int.MaxValue)
return (int)ul;
if (ul is uint.MaxValue or ulong.MaxValue)
return int.MaxValue;
throw new OverflowException();
}
///
long IConvertible.ToInt64(IFormatProvider provider)
{
var ul = Value;
if (ul < long.MaxValue)
return (long)ul;
if (ul is uint.MaxValue or ulong.MaxValue)
return long.MaxValue;
throw new OverflowException();
}
///
sbyte IConvertible.ToSByte(IFormatProvider provider)
{
var ul = Value;
if (ul < (ulong)sbyte.MaxValue)
return (sbyte)ul;
if (ul is uint.MaxValue or ulong.MaxValue)
return sbyte.MaxValue;
throw new OverflowException();
}
///
float IConvertible.ToSingle(IFormatProvider provider)
{
var ul = Value;
if (ul < float.MaxValue)
return ul;
if (ul is uint.MaxValue or ulong.MaxValue)
return float.MaxValue;
throw new OverflowException();
}
///
object IConvertible.ToType(Type conversionType, IFormatProvider provider) => ((IConvertible)Value).ToType(conversionType, provider);
///
ushort IConvertible.ToUInt16(IFormatProvider provider)
{
var ul = Value;
if (ul < (ulong)ushort.MaxValue)
return (ushort)ul;
if (ul is uint.MaxValue or ulong.MaxValue)
return ushort.MaxValue;
throw new OverflowException();
}
///
uint IConvertible.ToUInt32(IFormatProvider provider)
{
var ul = Value;
if (ul < uint.MaxValue)
return (uint)ul;
if (ul is uint.MaxValue or ulong.MaxValue)
return uint.MaxValue;
throw new OverflowException();
}
///
ulong IConvertible.ToUInt64(IFormatProvider provider) => Value;
internal class SizeTTypeConverter : UInt64Converter
{
public override object ConvertTo(ITypeDescriptorContext context, CultureInfo culture, object value, Type destinationType)
{
if (value is not SizeT sz) throw new ArgumentException();
return base.ConvertTo(context, culture, sz.Value, destinationType);
}
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value) =>
new SizeT((ulong)base.ConvertFrom(context, culture, value));
}
}
}