|
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
using System.Diagnostics.CodeAnalysis;
using System.Globalization;
using System.Numerics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using System.Runtime.Versioning;
namespace System
{
[Serializable]
[StructLayout(LayoutKind.Sequential)]
[TypeForwardedFrom("mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089")]
public readonly struct Byte
: IComparable,
IConvertible,
ISpanFormattable,
IComparable<byte>,
IEquatable<byte>,
IBinaryInteger<byte>,
IMinMaxValue<byte>,
IUnsignedNumber<byte>,
IUtf8SpanFormattable,
IUtfChar<byte>,
IBinaryIntegerParseAndFormatInfo<byte>
{
private readonly byte m_value; // Do not rename (binary serialization)
// The maximum value that a Byte may represent: 255.
public const byte MaxValue = (byte)0xFF;
// The minimum value that a Byte may represent: 0.
public const byte MinValue = 0;
/// <summary>Represents the additive identity (0).</summary>
private const byte AdditiveIdentity = 0;
/// <summary>Represents the multiplicative identity (1).</summary>
private const byte MultiplicativeIdentity = 1;
/// <summary>Represents the number one (1).</summary>
private const byte One = 1;
/// <summary>Represents the number zero (0).</summary>
private const byte Zero = 0;
// Compares this object to another object, returning an integer that
// indicates the relationship.
// Returns a value less than zero if this object
// null is considered to be less than any instance.
// If object is not of type byte, this method throws an ArgumentException.
//
public int CompareTo(object? value)
{
if (value == null)
{
return 1;
}
if (!(value is byte))
{
throw new ArgumentException(SR.Arg_MustBeByte);
}
return m_value - (((byte)value).m_value);
}
public int CompareTo(byte value)
{
return m_value - value;
}
// Determines whether two Byte objects are equal.
public override bool Equals([NotNullWhen(true)] object? obj)
{
if (!(obj is byte))
{
return false;
}
return m_value == ((byte)obj).m_value;
}
[NonVersionable]
public bool Equals(byte obj)
{
return m_value == obj;
}
// Gets a hash code for this instance.
public override int GetHashCode()
{
return m_value;
}
public static byte Parse(string s) => Parse(s, NumberStyles.Integer, provider: null);
public static byte Parse(string s, NumberStyles style) => Parse(s, style, provider: null);
public static byte Parse(string s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider);
public static byte Parse(string s, NumberStyles style, IFormatProvider? provider)
{
if (s is null) { ThrowHelper.ThrowArgumentNullException(ExceptionArgument.s); }
return Parse(s.AsSpan(), style, provider);
}
public static byte Parse(ReadOnlySpan<char> s, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
return Number.ParseBinaryInteger<char, byte>(s, style, NumberFormatInfo.GetInstance(provider));
}
public static bool TryParse([NotNullWhen(true)] string? s, out byte result) => TryParse(s, NumberStyles.Integer, provider: null, out result);
public static bool TryParse(ReadOnlySpan<char> s, out byte result) => TryParse(s, NumberStyles.Integer, provider: null, out result);
/// <summary>Tries to convert a UTF-8 character span containing the string representation of a number to its 8-bit unsigned integer equivalent.</summary>
/// <param name="utf8Text">A span containing the UTF-8 characters representing the number to convert.</param>
/// <param name="result">When this method returns, contains the 8-bit unsigned integer value equivalent to the number contained in <paramref name="utf8Text" /> if the conversion succeeded, or zero if the conversion failed. This parameter is passed uninitialized; any value originally supplied in result will be overwritten.</param>
/// <returns><c>true</c> if <paramref name="utf8Text" /> was converted successfully; otherwise, false.</returns>
public static bool TryParse(ReadOnlySpan<byte> utf8Text, out byte result) => TryParse(utf8Text, NumberStyles.Integer, provider: null, out result);
public static bool TryParse([NotNullWhen(true)] string? s, NumberStyles style, IFormatProvider? provider, out byte result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
if (s is null)
{
result = 0;
return false;
}
return Number.TryParseBinaryInteger(s.AsSpan(), style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK;
}
public static bool TryParse(ReadOnlySpan<char> s, NumberStyles style, IFormatProvider? provider, out byte result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
return Number.TryParseBinaryInteger(s, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK;
}
public override string ToString()
{
return Number.UInt32ToDecStr(m_value);
}
public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format)
{
return Number.FormatUInt32(m_value, format, null);
}
public string ToString(IFormatProvider? provider)
{
return Number.UInt32ToDecStr(m_value);
}
public string ToString([StringSyntax(StringSyntaxAttribute.NumericFormat)] string? format, IFormatProvider? provider)
{
return Number.FormatUInt32(m_value, format, provider);
}
public bool TryFormat(Span<char> destination, out int charsWritten, [StringSyntax(StringSyntaxAttribute.NumericFormat)] ReadOnlySpan<char> format = default, IFormatProvider? provider = null)
{
return Number.TryFormatUInt32(m_value, format, provider, destination, out charsWritten);
}
/// <inheritdoc cref="IUtf8SpanFormattable.TryFormat" />
public bool TryFormat(Span<byte> utf8Destination, out int bytesWritten, [StringSyntax(StringSyntaxAttribute.NumericFormat)] ReadOnlySpan<char> format = default, IFormatProvider? provider = null)
{
return Number.TryFormatUInt32(m_value, format, provider, utf8Destination, out bytesWritten);
}
//
// IConvertible
//
public TypeCode GetTypeCode()
{
return TypeCode.Byte;
}
bool IConvertible.ToBoolean(IFormatProvider? provider)
{
return Convert.ToBoolean(m_value);
}
char IConvertible.ToChar(IFormatProvider? provider)
{
return Convert.ToChar(m_value);
}
sbyte IConvertible.ToSByte(IFormatProvider? provider)
{
return Convert.ToSByte(m_value);
}
byte IConvertible.ToByte(IFormatProvider? provider)
{
return m_value;
}
short IConvertible.ToInt16(IFormatProvider? provider)
{
return Convert.ToInt16(m_value);
}
ushort IConvertible.ToUInt16(IFormatProvider? provider)
{
return Convert.ToUInt16(m_value);
}
int IConvertible.ToInt32(IFormatProvider? provider)
{
return Convert.ToInt32(m_value);
}
uint IConvertible.ToUInt32(IFormatProvider? provider)
{
return Convert.ToUInt32(m_value);
}
long IConvertible.ToInt64(IFormatProvider? provider)
{
return Convert.ToInt64(m_value);
}
ulong IConvertible.ToUInt64(IFormatProvider? provider)
{
return Convert.ToUInt64(m_value);
}
float IConvertible.ToSingle(IFormatProvider? provider)
{
return Convert.ToSingle(m_value);
}
double IConvertible.ToDouble(IFormatProvider? provider)
{
return Convert.ToDouble(m_value);
}
decimal IConvertible.ToDecimal(IFormatProvider? provider)
{
return Convert.ToDecimal(m_value);
}
DateTime IConvertible.ToDateTime(IFormatProvider? provider)
{
throw new InvalidCastException(SR.Format(SR.InvalidCast_FromTo, "Byte", "DateTime"));
}
object IConvertible.ToType(Type type, IFormatProvider? provider)
{
return Convert.DefaultToType((IConvertible)this, type, provider);
}
//
// IAdditionOperators
//
/// <inheritdoc cref="IAdditionOperators{TSelf, TOther, TResult}.op_Addition(TSelf, TOther)" />
static byte IAdditionOperators<byte, byte, byte>.operator +(byte left, byte right) => (byte)(left + right);
/// <inheritdoc cref="IAdditionOperators{TSelf, TOther, TResult}.op_CheckedAddition(TSelf, TOther)" />
static byte IAdditionOperators<byte, byte, byte>.operator checked +(byte left, byte right) => checked((byte)(left + right));
//
// IAdditiveIdentity
//
/// <inheritdoc cref="IAdditiveIdentity{TSelf, TResult}.AdditiveIdentity" />
static byte IAdditiveIdentity<byte, byte>.AdditiveIdentity => AdditiveIdentity;
//
// IBinaryInteger
//
/// <inheritdoc cref="IBinaryInteger{TSelf}.DivRem(TSelf, TSelf)" />
public static (byte Quotient, byte Remainder) DivRem(byte left, byte right) => Math.DivRem(left, right);
/// <inheritdoc cref="IBinaryInteger{TSelf}.LeadingZeroCount(TSelf)" />
public static byte LeadingZeroCount(byte value) => (byte)(BitOperations.LeadingZeroCount(value) - 24);
/// <inheritdoc cref="IBinaryInteger{TSelf}.PopCount(TSelf)" />
public static byte PopCount(byte value) => (byte)BitOperations.PopCount(value);
/// <inheritdoc cref="IBinaryInteger{TSelf}.RotateLeft(TSelf, int)" />
public static byte RotateLeft(byte value, int rotateAmount) => (byte)((value << (rotateAmount & 7)) | (value >> ((8 - rotateAmount) & 7)));
/// <inheritdoc cref="IBinaryInteger{TSelf}.RotateRight(TSelf, int)" />
public static byte RotateRight(byte value, int rotateAmount) => (byte)((value >> (rotateAmount & 7)) | (value << ((8 - rotateAmount) & 7)));
/// <inheritdoc cref="IBinaryInteger{TSelf}.TrailingZeroCount(TSelf)" />
public static byte TrailingZeroCount(byte value) => (byte)(BitOperations.TrailingZeroCount(value << 24) - 24);
/// <inheritdoc cref="IBinaryInteger{TSelf}.TryReadBigEndian(ReadOnlySpan{byte}, bool, out TSelf)" />
static bool IBinaryInteger<byte>.TryReadBigEndian(ReadOnlySpan<byte> source, bool isUnsigned, out byte value)
{
byte result = default;
if (source.Length != 0)
{
if (!isUnsigned && sbyte.IsNegative((sbyte)source[0]))
{
// When we are signed and the sign bit is set we are negative and therefore
// definitely out of range
value = result;
return false;
}
if ((source.Length > sizeof(byte)) && (source[..^sizeof(byte)].ContainsAnyExcept((byte)0x00)))
{
// When we have any non-zero leading data, we are a large positive and therefore
// definitely out of range
value = result;
return false;
}
// We only have 1-byte so read it directly
result = Unsafe.Add(ref MemoryMarshal.GetReference(source), source.Length - sizeof(byte));
}
value = result;
return true;
}
/// <inheritdoc cref="IBinaryInteger{TSelf}.TryReadLittleEndian(ReadOnlySpan{byte}, bool, out TSelf)" />
static bool IBinaryInteger<byte>.TryReadLittleEndian(ReadOnlySpan<byte> source, bool isUnsigned, out byte value)
{
byte result = default;
if (source.Length != 0)
{
if (!isUnsigned && sbyte.IsNegative((sbyte)source[^1]))
{
// When we are signed and the sign bit is set, we are negative and therefore
// definitely out of range
value = result;
return false;
}
if ((source.Length > sizeof(byte)) && (source[sizeof(byte)..].ContainsAnyExcept((byte)0x00)))
{
// When we have any non-zero leading data, we are a large positive and therefore
// definitely out of range
value = result;
return false;
}
// We only have 1-byte so read it directly
result = MemoryMarshal.GetReference(source);
}
value = result;
return true;
}
/// <inheritdoc cref="IBinaryInteger{TSelf}.GetShortestBitLength()" />
int IBinaryInteger<byte>.GetShortestBitLength() => (sizeof(byte) * 8) - LeadingZeroCount(m_value);
/// <inheritdoc cref="IBinaryInteger{TSelf}.GetByteCount()" />
int IBinaryInteger<byte>.GetByteCount() => sizeof(byte);
/// <inheritdoc cref="IBinaryInteger{TSelf}.TryWriteBigEndian(Span{byte}, out int)" />
bool IBinaryInteger<byte>.TryWriteBigEndian(Span<byte> destination, out int bytesWritten)
{
if (destination.Length >= sizeof(byte))
{
byte value = m_value;
MemoryMarshal.GetReference(destination) = value;
bytesWritten = sizeof(byte);
return true;
}
else
{
bytesWritten = 0;
return false;
}
}
/// <inheritdoc cref="IBinaryInteger{TSelf}.TryWriteLittleEndian(Span{byte}, out int)" />
bool IBinaryInteger<byte>.TryWriteLittleEndian(Span<byte> destination, out int bytesWritten)
{
if (destination.Length >= sizeof(byte))
{
byte value = m_value;
MemoryMarshal.GetReference(destination) = value;
bytesWritten = sizeof(byte);
return true;
}
else
{
bytesWritten = 0;
return false;
}
}
//
// IBinaryNumber
//
/// <inheritdoc cref="IBinaryNumber{TSelf}.AllBitsSet" />
static byte IBinaryNumber<byte>.AllBitsSet => MaxValue;
/// <inheritdoc cref="IBinaryNumber{TSelf}.IsPow2(TSelf)" />
public static bool IsPow2(byte value) => BitOperations.IsPow2((uint)value);
/// <inheritdoc cref="IBinaryNumber{TSelf}.Log2(TSelf)" />
public static byte Log2(byte value) => (byte)BitOperations.Log2(value);
//
// IBitwiseOperators
//
/// <inheritdoc cref="IBitwiseOperators{TSelf, TOther, TResult}.op_BitwiseAnd(TSelf, TOther)" />
static byte IBitwiseOperators<byte, byte, byte>.operator &(byte left, byte right) => (byte)(left & right);
/// <inheritdoc cref="IBitwiseOperators{TSelf, TOther, TResult}.op_BitwiseOr(TSelf, TOther)" />
static byte IBitwiseOperators<byte, byte, byte>.operator |(byte left, byte right) => (byte)(left | right);
/// <inheritdoc cref="IBitwiseOperators{TSelf, TOther, TResult}.op_ExclusiveOr(TSelf, TOther)" />
static byte IBitwiseOperators<byte, byte, byte>.operator ^(byte left, byte right) => (byte)(left ^ right);
/// <inheritdoc cref="IBitwiseOperators{TSelf, TOther, TResult}.op_OnesComplement(TSelf)" />
static byte IBitwiseOperators<byte, byte, byte>.operator ~(byte value) => (byte)(~value);
//
// IComparisonOperators
//
/// <inheritdoc cref="IComparisonOperators{TSelf, TOther, TResult}.op_LessThan(TSelf, TOther)" />
static bool IComparisonOperators<byte, byte, bool>.operator <(byte left, byte right) => left < right;
/// <inheritdoc cref="IComparisonOperators{TSelf, TOther, TResult}.op_LessThanOrEqual(TSelf, TOther)" />
static bool IComparisonOperators<byte, byte, bool>.operator <=(byte left, byte right) => left <= right;
/// <inheritdoc cref="IComparisonOperators{TSelf, TOther, TResult}.op_GreaterThan(TSelf, TOther)" />
static bool IComparisonOperators<byte, byte, bool>.operator >(byte left, byte right) => left > right;
/// <inheritdoc cref="IComparisonOperators{TSelf, TOther, TResult}.op_GreaterThanOrEqual(TSelf, TOther)" />
static bool IComparisonOperators<byte, byte, bool>.operator >=(byte left, byte right) => left >= right;
//
// IDecrementOperators
//
/// <inheritdoc cref="IDecrementOperators{TSelf}.op_Decrement(TSelf)" />
static byte IDecrementOperators<byte>.operator --(byte value) => --value;
/// <inheritdoc cref="IDecrementOperators{TSelf}.op_CheckedDecrement(TSelf)" />
static byte IDecrementOperators<byte>.operator checked --(byte value) => checked(--value);
//
// IDivisionOperators
//
/// <inheritdoc cref="IDivisionOperators{TSelf, TOther, TResult}.op_Division(TSelf, TOther)" />
static byte IDivisionOperators<byte, byte, byte>.operator /(byte left, byte right) => (byte)(left / right);
//
// IEqualityOperators
//
/// <inheritdoc cref="IEqualityOperators{TSelf, TOther, TResult}.op_Equality(TSelf, TOther)" />
static bool IEqualityOperators<byte, byte, bool>.operator ==(byte left, byte right) => left == right;
/// <inheritdoc cref="IEqualityOperators{TSelf, TOther, TResult}.op_Inequality(TSelf, TOther)" />
static bool IEqualityOperators<byte, byte, bool>.operator !=(byte left, byte right) => left != right;
//
// IIncrementOperators
//
/// <inheritdoc cref="IIncrementOperators{TSelf}.op_Increment(TSelf)" />
static byte IIncrementOperators<byte>.operator ++(byte value) => ++value;
/// <inheritdoc cref="IIncrementOperators{TSelf}.op_CheckedIncrement(TSelf)" />
static byte IIncrementOperators<byte>.operator checked ++(byte value) => checked(++value);
//
// IMinMaxValue
//
/// <inheritdoc cref="IMinMaxValue{TSelf}.MinValue" />
static byte IMinMaxValue<byte>.MinValue => MinValue;
/// <inheritdoc cref="IMinMaxValue{TSelf}.MaxValue" />
static byte IMinMaxValue<byte>.MaxValue => MaxValue;
//
// IModulusOperators
//
/// <inheritdoc cref="IModulusOperators{TSelf, TOther, TResult}.op_Modulus(TSelf, TOther)" />
static byte IModulusOperators<byte, byte, byte>.operator %(byte left, byte right) => (byte)(left % right);
//
// IMultiplicativeIdentity
//
/// <inheritdoc cref="IMultiplicativeIdentity{TSelf, TResult}.MultiplicativeIdentity" />
static byte IMultiplicativeIdentity<byte, byte>.MultiplicativeIdentity => MultiplicativeIdentity;
//
// IMultiplyOperators
//
/// <inheritdoc cref="IMultiplyOperators{TSelf, TOther, TResult}.op_Multiply(TSelf, TOther)" />
static byte IMultiplyOperators<byte, byte, byte>.operator *(byte left, byte right) => (byte)(left * right);
/// <inheritdoc cref="IMultiplyOperators{TSelf, TOther, TResult}.op_CheckedMultiply(TSelf, TOther)" />
static byte IMultiplyOperators<byte, byte, byte>.operator checked *(byte left, byte right) => checked((byte)(left * right));
//
// INumber
//
/// <inheritdoc cref="INumber{TSelf}.Clamp(TSelf, TSelf, TSelf)" />
public static byte Clamp(byte value, byte min, byte max) => Math.Clamp(value, min, max);
/// <inheritdoc cref="INumber{TSelf}.CopySign(TSelf, TSelf)" />
static byte INumber<byte>.CopySign(byte value, byte sign) => value;
/// <inheritdoc cref="INumber{TSelf}.Max(TSelf, TSelf)" />
public static byte Max(byte x, byte y) => Math.Max(x, y);
/// <inheritdoc cref="INumber{TSelf}.MaxNumber(TSelf, TSelf)" />
static byte INumber<byte>.MaxNumber(byte x, byte y) => Max(x, y);
/// <inheritdoc cref="INumber{TSelf}.Min(TSelf, TSelf)" />
public static byte Min(byte x, byte y) => Math.Min(x, y);
/// <inheritdoc cref="INumber{TSelf}.MinNumber(TSelf, TSelf)" />
static byte INumber<byte>.MinNumber(byte x, byte y) => Min(x, y);
/// <inheritdoc cref="INumber{TSelf}.Sign(TSelf)" />
public static int Sign(byte value) => (value == 0) ? 0 : 1;
//
// INumberBase
//
/// <inheritdoc cref="INumberBase{TSelf}.One" />
static byte INumberBase<byte>.One => One;
/// <inheritdoc cref="INumberBase{TSelf}.Radix" />
static int INumberBase<byte>.Radix => 2;
/// <inheritdoc cref="INumberBase{TSelf}.Zero" />
static byte INumberBase<byte>.Zero => Zero;
/// <inheritdoc cref="INumberBase{TSelf}.Abs(TSelf)" />
static byte INumberBase<byte>.Abs(byte value) => value;
/// <inheritdoc cref="INumberBase{TSelf}.CreateChecked{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte CreateChecked<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
byte result;
if (typeof(TOther) == typeof(byte))
{
result = (byte)(object)value;
}
else if (!TryConvertFromChecked(value, out result) && !TOther.TryConvertToChecked(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}
return result;
}
/// <inheritdoc cref="INumberBase{TSelf}.CreateSaturating{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte CreateSaturating<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
byte result;
if (typeof(TOther) == typeof(byte))
{
result = (byte)(object)value;
}
else if (!TryConvertFromSaturating(value, out result) && !TOther.TryConvertToSaturating(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}
return result;
}
/// <inheritdoc cref="INumberBase{TSelf}.CreateTruncating{TOther}(TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static byte CreateTruncating<TOther>(TOther value)
where TOther : INumberBase<TOther>
{
byte result;
if (typeof(TOther) == typeof(byte))
{
result = (byte)(object)value;
}
else if (!TryConvertFromTruncating(value, out result) && !TOther.TryConvertToTruncating(value, out result))
{
ThrowHelper.ThrowNotSupportedException();
}
return result;
}
/// <inheritdoc cref="INumberBase{TSelf}.IsCanonical(TSelf)" />
static bool INumberBase<byte>.IsCanonical(byte value) => true;
/// <inheritdoc cref="INumberBase{TSelf}.IsComplexNumber(TSelf)" />
static bool INumberBase<byte>.IsComplexNumber(byte value) => false;
/// <inheritdoc cref="INumberBase{TSelf}.IsEvenInteger(TSelf)" />
public static bool IsEvenInteger(byte value) => (value & 1) == 0;
/// <inheritdoc cref="INumberBase{TSelf}.IsFinite(TSelf)" />
static bool INumberBase<byte>.IsFinite(byte value) => true;
/// <inheritdoc cref="INumberBase{TSelf}.IsImaginaryNumber(TSelf)" />
static bool INumberBase<byte>.IsImaginaryNumber(byte value) => false;
/// <inheritdoc cref="INumberBase{TSelf}.IsInfinity(TSelf)" />
static bool INumberBase<byte>.IsInfinity(byte value) => false;
/// <inheritdoc cref="INumberBase{TSelf}.IsInteger(TSelf)" />
static bool INumberBase<byte>.IsInteger(byte value) => true;
/// <inheritdoc cref="INumberBase{TSelf}.IsNaN(TSelf)" />
static bool INumberBase<byte>.IsNaN(byte value) => false;
/// <inheritdoc cref="INumberBase{TSelf}.IsNegative(TSelf)" />
static bool INumberBase<byte>.IsNegative(byte value) => false;
/// <inheritdoc cref="INumberBase{TSelf}.IsNegativeInfinity(TSelf)" />
static bool INumberBase<byte>.IsNegativeInfinity(byte value) => false;
/// <inheritdoc cref="INumberBase{TSelf}.IsNormal(TSelf)" />
static bool INumberBase<byte>.IsNormal(byte value) => value != 0;
/// <inheritdoc cref="INumberBase{TSelf}.IsOddInteger(TSelf)" />
public static bool IsOddInteger(byte value) => (value & 1) != 0;
/// <inheritdoc cref="INumberBase{TSelf}.IsPositive(TSelf)" />
static bool INumberBase<byte>.IsPositive(byte value) => true;
/// <inheritdoc cref="INumberBase{TSelf}.IsPositiveInfinity(TSelf)" />
static bool INumberBase<byte>.IsPositiveInfinity(byte value) => false;
/// <inheritdoc cref="INumberBase{TSelf}.IsRealNumber(TSelf)" />
static bool INumberBase<byte>.IsRealNumber(byte value) => true;
/// <inheritdoc cref="INumberBase{TSelf}.IsSubnormal(TSelf)" />
static bool INumberBase<byte>.IsSubnormal(byte value) => false;
/// <inheritdoc cref="INumberBase{TSelf}.IsZero(TSelf)" />
static bool INumberBase<byte>.IsZero(byte value) => (value == 0);
/// <inheritdoc cref="INumberBase{TSelf}.MaxMagnitude(TSelf, TSelf)" />
static byte INumberBase<byte>.MaxMagnitude(byte x, byte y) => Max(x, y);
/// <inheritdoc cref="INumberBase{TSelf}.MaxMagnitudeNumber(TSelf, TSelf)" />
static byte INumberBase<byte>.MaxMagnitudeNumber(byte x, byte y) => Max(x, y);
/// <inheritdoc cref="INumberBase{TSelf}.MinMagnitude(TSelf, TSelf)" />
static byte INumberBase<byte>.MinMagnitude(byte x, byte y) => Min(x, y);
/// <inheritdoc cref="INumberBase{TSelf}.MinMagnitudeNumber(TSelf, TSelf)" />
static byte INumberBase<byte>.MinMagnitudeNumber(byte x, byte y) => Min(x, y);
/// <inheritdoc cref="INumberBase{TSelf}.MultiplyAddEstimate(TSelf, TSelf, TSelf)" />
static byte INumberBase<byte>.MultiplyAddEstimate(byte left, byte right, byte addend) => (byte)((left * right) + addend);
/// <inheritdoc cref="INumberBase{TSelf}.TryConvertFromChecked{TOther}(TOther, out TSelf)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool INumberBase<byte>.TryConvertFromChecked<TOther>(TOther value, out byte result) => TryConvertFromChecked(value, out result);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryConvertFromChecked<TOther>(TOther value, out byte result)
where TOther : INumberBase<TOther>
{
// In order to reduce overall code duplication and improve the inlinabilty of these
// methods for the corelib types we have `ConvertFrom` handle the same sign and
// `ConvertTo` handle the opposite sign. However, since there is an uneven split
// between signed and unsigned types, the one that handles unsigned will also
// handle `Decimal`.
//
// That is, `ConvertFrom` for `byte` will handle the other unsigned types and
// `ConvertTo` will handle the signed types
if (typeof(TOther) == typeof(char))
{
char actualValue = (char)(object)value;
result = checked((byte)actualValue);
return true;
}
else if (typeof(TOther) == typeof(decimal))
{
decimal actualValue = (decimal)(object)value;
result = checked((byte)actualValue);
return true;
}
else if (typeof(TOther) == typeof(ushort))
{
ushort actualValue = (ushort)(object)value;
result = checked((byte)actualValue);
return true;
}
else if (typeof(TOther) == typeof(uint))
{
uint actualValue = (uint)(object)value;
result = checked((byte)actualValue);
return true;
}
else if (typeof(TOther) == typeof(ulong))
{
ulong actualValue = (ulong)(object)value;
result = checked((byte)actualValue);
return true;
}
else if (typeof(TOther) == typeof(UInt128))
{
UInt128 actualValue = (UInt128)(object)value;
result = checked((byte)actualValue);
return true;
}
else if (typeof(TOther) == typeof(nuint))
{
nuint actualValue = (nuint)(object)value;
result = checked((byte)actualValue);
return true;
}
else
{
result = default;
return false;
}
}
/// <inheritdoc cref="INumberBase{TSelf}.TryConvertFromSaturating{TOther}(TOther, out TSelf)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool INumberBase<byte>.TryConvertFromSaturating<TOther>(TOther value, out byte result) => TryConvertFromSaturating(value, out result);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryConvertFromSaturating<TOther>(TOther value, out byte result)
where TOther : INumberBase<TOther>
{
// In order to reduce overall code duplication and improve the inlinabilty of these
// methods for the corelib types we have `ConvertFrom` handle the same sign and
// `ConvertTo` handle the opposite sign. However, since there is an uneven split
// between signed and unsigned types, the one that handles unsigned will also
// handle `Decimal`.
//
// That is, `ConvertFrom` for `byte` will handle the other unsigned types and
// `ConvertTo` will handle the signed types
if (typeof(TOther) == typeof(char))
{
char actualValue = (char)(object)value;
result = (actualValue >= MaxValue) ? MaxValue : (byte)actualValue;
return true;
}
else if (typeof(TOther) == typeof(decimal))
{
decimal actualValue = (decimal)(object)value;
result = (actualValue >= MaxValue) ? MaxValue :
(actualValue <= MinValue) ? MinValue : (byte)actualValue;
return true;
}
else if (typeof(TOther) == typeof(ushort))
{
ushort actualValue = (ushort)(object)value;
result = (actualValue >= MaxValue) ? MaxValue : (byte)actualValue;
return true;
}
else if (typeof(TOther) == typeof(uint))
{
uint actualValue = (uint)(object)value;
result = (actualValue >= MaxValue) ? MaxValue : (byte)actualValue;
return true;
}
else if (typeof(TOther) == typeof(ulong))
{
ulong actualValue = (ulong)(object)value;
result = (actualValue >= MaxValue) ? MaxValue : (byte)actualValue;
return true;
}
else if (typeof(TOther) == typeof(UInt128))
{
UInt128 actualValue = (UInt128)(object)value;
result = (actualValue >= MaxValue) ? MaxValue : (byte)actualValue;
return true;
}
else if (typeof(TOther) == typeof(nuint))
{
nuint actualValue = (nuint)(object)value;
result = (actualValue >= MaxValue) ? MaxValue : (byte)actualValue;
return true;
}
else
{
result = default;
return false;
}
}
/// <inheritdoc cref="INumberBase{TSelf}.TryConvertFromTruncating{TOther}(TOther, out TSelf)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool INumberBase<byte>.TryConvertFromTruncating<TOther>(TOther value, out byte result) => TryConvertFromTruncating(value, out result);
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static bool TryConvertFromTruncating<TOther>(TOther value, out byte result)
where TOther : INumberBase<TOther>
{
// In order to reduce overall code duplication and improve the inlinabilty of these
// methods for the corelib types we have `ConvertFrom` handle the same sign and
// `ConvertTo` handle the opposite sign. However, since there is an uneven split
// between signed and unsigned types, the one that handles unsigned will also
// handle `Decimal`.
//
// That is, `ConvertFrom` for `byte` will handle the other unsigned types and
// `ConvertTo` will handle the signed types
if (typeof(TOther) == typeof(char))
{
char actualValue = (char)(object)value;
result = (byte)actualValue;
return true;
}
else if (typeof(TOther) == typeof(decimal))
{
decimal actualValue = (decimal)(object)value;
result = (actualValue >= MaxValue) ? MaxValue :
(actualValue <= MinValue) ? MinValue : (byte)actualValue;
return true;
}
else if (typeof(TOther) == typeof(ushort))
{
ushort actualValue = (ushort)(object)value;
result = (byte)actualValue;
return true;
}
else if (typeof(TOther) == typeof(uint))
{
uint actualValue = (uint)(object)value;
result = (byte)actualValue;
return true;
}
else if (typeof(TOther) == typeof(ulong))
{
ulong actualValue = (ulong)(object)value;
result = (byte)actualValue;
return true;
}
else if (typeof(TOther) == typeof(UInt128))
{
UInt128 actualValue = (UInt128)(object)value;
result = (byte)actualValue;
return true;
}
else if (typeof(TOther) == typeof(nuint))
{
nuint actualValue = (nuint)(object)value;
result = (byte)actualValue;
return true;
}
else
{
result = default;
return false;
}
}
/// <inheritdoc cref="INumberBase{TSelf}.TryConvertToChecked{TOther}(TSelf, out TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool INumberBase<byte>.TryConvertToChecked<TOther>(byte value, [MaybeNullWhen(false)] out TOther result)
{
// In order to reduce overall code duplication and improve the inlinabilty of these
// methods for the corelib types we have `ConvertFrom` handle the same sign and
// `ConvertTo` handle the opposite sign. However, since there is an uneven split
// between signed and unsigned types, the one that handles unsigned will also
// handle `Decimal`.
//
// That is, `ConvertFrom` for `byte` will handle the other unsigned types and
// `ConvertTo` will handle the unsigned types
if (typeof(TOther) == typeof(double))
{
double actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(Half))
{
Half actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(short))
{
short actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(int))
{
int actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(long))
{
long actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(Int128))
{
Int128 actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(nint))
{
nint actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(sbyte))
{
sbyte actualResult = checked((sbyte)value);
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(float))
{
float actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else
{
result = default;
return false;
}
}
/// <inheritdoc cref="INumberBase{TSelf}.TryConvertToSaturating{TOther}(TSelf, out TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool INumberBase<byte>.TryConvertToSaturating<TOther>(byte value, [MaybeNullWhen(false)] out TOther result)
{
// In order to reduce overall code duplication and improve the inlinabilty of these
// methods for the corelib types we have `ConvertFrom` handle the same sign and
// `ConvertTo` handle the opposite sign. However, since there is an uneven split
// between signed and unsigned types, the one that handles unsigned will also
// handle `Decimal`.
//
// That is, `ConvertFrom` for `byte` will handle the other unsigned types and
// `ConvertTo` will handle the unsigned types
if (typeof(TOther) == typeof(double))
{
double actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(Half))
{
Half actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(short))
{
short actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(int))
{
int actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(long))
{
long actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(Int128))
{
Int128 actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(nint))
{
nint actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(sbyte))
{
sbyte actualResult = (value >= sbyte.MaxValue) ? sbyte.MaxValue : (sbyte)value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(float))
{
float actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else
{
result = default;
return false;
}
}
/// <inheritdoc cref="INumberBase{TSelf}.TryConvertToTruncating{TOther}(TSelf, out TOther)" />
[MethodImpl(MethodImplOptions.AggressiveInlining)]
static bool INumberBase<byte>.TryConvertToTruncating<TOther>(byte value, [MaybeNullWhen(false)] out TOther result)
{
// In order to reduce overall code duplication and improve the inlinabilty of these
// methods for the corelib types we have `ConvertFrom` handle the same sign and
// `ConvertTo` handle the opposite sign. However, since there is an uneven split
// between signed and unsigned types, the one that handles unsigned will also
// handle `Decimal`.
//
// That is, `ConvertFrom` for `byte` will handle the other unsigned types and
// `ConvertTo` will handle the unsigned types
if (typeof(TOther) == typeof(double))
{
double actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(Half))
{
Half actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(short))
{
short actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(int))
{
int actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(long))
{
long actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(Int128))
{
Int128 actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(nint))
{
nint actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(sbyte))
{
sbyte actualResult = (sbyte)value;
result = (TOther)(object)actualResult;
return true;
}
else if (typeof(TOther) == typeof(float))
{
float actualResult = value;
result = (TOther)(object)actualResult;
return true;
}
else
{
result = default;
return false;
}
}
//
// IParsable
//
/// <inheritdoc cref="IParsable{TSelf}.TryParse(string?, IFormatProvider?, out TSelf)" />
public static bool TryParse([NotNullWhen(true)] string? s, IFormatProvider? provider, out byte result) => TryParse(s, NumberStyles.Integer, provider, out result);
//
// IShiftOperators
//
/// <inheritdoc cref="IShiftOperators{TSelf, TOther, TResult}.op_LeftShift(TSelf, TOther)" />
static byte IShiftOperators<byte, int, byte>.operator <<(byte value, int shiftAmount) => (byte)(value << (shiftAmount & 7));
/// <inheritdoc cref="IShiftOperators{TSelf, TOther, TResult}.op_RightShift(TSelf, TOther)" />
static byte IShiftOperators<byte, int, byte>.operator >>(byte value, int shiftAmount) => (byte)(value >> (shiftAmount & 7));
/// <inheritdoc cref="IShiftOperators{TSelf, TOther, TResult}.op_UnsignedRightShift(TSelf, TOther)" />
static byte IShiftOperators<byte, int, byte>.operator >>>(byte value, int shiftAmount) => (byte)(value >>> (shiftAmount & 7));
//
// ISpanParsable
//
/// <inheritdoc cref="ISpanParsable{TSelf}.Parse(ReadOnlySpan{char}, IFormatProvider?)" />
public static byte Parse(ReadOnlySpan<char> s, IFormatProvider? provider) => Parse(s, NumberStyles.Integer, provider);
/// <inheritdoc cref="ISpanParsable{TSelf}.TryParse(ReadOnlySpan{char}, IFormatProvider?, out TSelf)" />
public static bool TryParse(ReadOnlySpan<char> s, IFormatProvider? provider, out byte result) => TryParse(s, NumberStyles.Integer, provider, out result);
//
// ISubtractionOperators
//
/// <inheritdoc cref="ISubtractionOperators{TSelf, TOther, TResult}.op_Subtraction(TSelf, TOther)" />
static byte ISubtractionOperators<byte, byte, byte>.operator -(byte left, byte right) => (byte)(left - right);
/// <inheritdoc cref="ISubtractionOperators{TSelf, TOther, TResult}.op_CheckedSubtraction(TSelf, TOther)" />
static byte ISubtractionOperators<byte, byte, byte>.operator checked -(byte left, byte right) => checked((byte)(left - right));
//
// IUnaryNegationOperators
//
/// <inheritdoc cref="IUnaryNegationOperators{TSelf, TResult}.op_UnaryNegation(TSelf)" />
static byte IUnaryNegationOperators<byte, byte>.operator -(byte value) => (byte)(-value);
/// <inheritdoc cref="IUnaryNegationOperators{TSelf, TResult}.op_CheckedUnaryNegation(TSelf)" />
static byte IUnaryNegationOperators<byte, byte>.operator checked -(byte value) => checked((byte)(-value));
//
// IUnaryPlusOperators
//
/// <inheritdoc cref="IUnaryPlusOperators{TSelf, TResult}.op_UnaryPlus(TSelf)" />
static byte IUnaryPlusOperators<byte, byte>.operator +(byte value) => (byte)(+value);
//
// IUtf8SpanParsable
//
/// <inheritdoc cref="INumberBase{TSelf}.Parse(ReadOnlySpan{byte}, NumberStyles, IFormatProvider?)" />
public static byte Parse(ReadOnlySpan<byte> utf8Text, NumberStyles style = NumberStyles.Integer, IFormatProvider? provider = null)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
return Number.ParseBinaryInteger<byte, byte>(utf8Text, style, NumberFormatInfo.GetInstance(provider));
}
/// <inheritdoc cref="INumberBase{TSelf}.TryParse(ReadOnlySpan{byte}, NumberStyles, IFormatProvider?, out TSelf)" />
public static bool TryParse(ReadOnlySpan<byte> utf8Text, NumberStyles style, IFormatProvider? provider, out byte result)
{
NumberFormatInfo.ValidateParseStyleInteger(style);
return Number.TryParseBinaryInteger(utf8Text, style, NumberFormatInfo.GetInstance(provider), out result) == Number.ParsingStatus.OK;
}
/// <inheritdoc cref="IUtf8SpanParsable{TSelf}.Parse(ReadOnlySpan{byte}, IFormatProvider?)" />
public static byte Parse(ReadOnlySpan<byte> utf8Text, IFormatProvider? provider) => Parse(utf8Text, NumberStyles.Integer, provider);
/// <inheritdoc cref="IUtf8SpanParsable{TSelf}.TryParse(ReadOnlySpan{byte}, IFormatProvider?, out TSelf)" />
public static bool TryParse(ReadOnlySpan<byte> utf8Text, IFormatProvider? provider, out byte result) => TryParse(utf8Text, NumberStyles.Integer, provider, out result);
//
// IUtfChar
//
static byte IUtfChar<byte>.CastFrom(byte value) => value;
static byte IUtfChar<byte>.CastFrom(char value) => (byte)value;
static byte IUtfChar<byte>.CastFrom(int value) => (byte)value;
static byte IUtfChar<byte>.CastFrom(uint value) => (byte)value;
static byte IUtfChar<byte>.CastFrom(ulong value) => (byte)value;
static uint IUtfChar<byte>.CastToUInt32(byte value) => value;
//
// IBinaryIntegerParseAndFormatInfo
//
static bool IBinaryIntegerParseAndFormatInfo<byte>.IsSigned => false;
static int IBinaryIntegerParseAndFormatInfo<byte>.MaxDigitCount => 3; // 255
static int IBinaryIntegerParseAndFormatInfo<byte>.MaxHexDigitCount => 2; // 0xFF
static byte IBinaryIntegerParseAndFormatInfo<byte>.MaxValueDiv10 => MaxValue / 10;
static string IBinaryIntegerParseAndFormatInfo<byte>.OverflowMessage => SR.Overflow_Byte;
static bool IBinaryIntegerParseAndFormatInfo<byte>.IsGreaterThanAsUnsigned(byte left, byte right) => left > right;
static byte IBinaryIntegerParseAndFormatInfo<byte>.MultiplyBy10(byte value) => (byte)(value * 10);
static byte IBinaryIntegerParseAndFormatInfo<byte>.MultiplyBy16(byte value) => (byte)(value * 16);
}
}
|