Create a (Discord)Color using a string (#2979)
* Create a (Discord)Color using a string * You made me learn bitwise operators and shifting I am angery now, also AI sucks at this shit * xmldoc * Apply suggestions from code review --------- Co-authored-by: Mihail Gribkov <61027276+Misha-133@users.noreply.github.com>
This commit is contained in:
@@ -200,6 +200,94 @@ namespace Discord
|
|||||||
public static implicit operator uint(Color color)
|
public static implicit operator uint(Color color)
|
||||||
=> color.RawValue;
|
=> color.RawValue;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the string representation of a color to a Color object.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rawValue">String to be parsed to a color</param>
|
||||||
|
/// <param name="colorType">Color format of the string</param>
|
||||||
|
/// <returns>A Color object with a color value parsed from a string</returns>
|
||||||
|
/// <exception cref="ArgumentOutOfRangeException">The argument is not a number or of incorrect length</exception>
|
||||||
|
public static Color Parse(string rawValue, ColorType colorType = ColorType.CssHexColor)
|
||||||
|
{
|
||||||
|
if (TryParse(rawValue, out var color, colorType))
|
||||||
|
return color;
|
||||||
|
|
||||||
|
throw new ArgumentOutOfRangeException(nameof(rawValue), "Value must be a number of valid length - matching the specified ColorType");
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Converts the string representation of a color to a Color object. The return value indicates whether the conversion succeeded.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rawValue">String to be parsed to a color</param>
|
||||||
|
/// <param name="color">When this method returns true, contains a Color that represents the parsed string.</param>
|
||||||
|
/// <param name="colorType">Color format of the string</param>
|
||||||
|
/// <returns>true if the conversion succeeded; false otherwise.</returns>
|
||||||
|
public static bool TryParse(string rawValue, out Color color, ColorType colorType = ColorType.CssHexColor)
|
||||||
|
{
|
||||||
|
color = new Color();
|
||||||
|
|
||||||
|
if (string.IsNullOrWhiteSpace(rawValue))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
rawValue = rawValue.TrimStart('#');
|
||||||
|
|
||||||
|
if (rawValue.StartsWith("0x"))
|
||||||
|
rawValue = rawValue.Substring(2);
|
||||||
|
|
||||||
|
if (!uint.TryParse(rawValue, System.Globalization.NumberStyles.HexNumber, null, out var parsedValue))
|
||||||
|
return false;
|
||||||
|
|
||||||
|
uint r;
|
||||||
|
uint g;
|
||||||
|
uint b;
|
||||||
|
uint fullHex;
|
||||||
|
|
||||||
|
switch (rawValue.Length, colorType)
|
||||||
|
{
|
||||||
|
case (3, ColorType.CssHexColor):
|
||||||
|
r = parsedValue >> 8;
|
||||||
|
g = (parsedValue & 0xF0) >> 4;
|
||||||
|
b = parsedValue & 0xF;
|
||||||
|
|
||||||
|
r = (r << 4) | r;
|
||||||
|
g = (g << 4) | g;
|
||||||
|
b = (b << 4) | b;
|
||||||
|
|
||||||
|
fullHex = (r << 16) | (g << 8) | b;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (4, ColorType.CssHexColor):
|
||||||
|
r = (parsedValue & 0xF00) >> 8;
|
||||||
|
g = (parsedValue & 0xF0) >> 4;
|
||||||
|
b = parsedValue & 0xF;
|
||||||
|
|
||||||
|
r = (r << 4) | r;
|
||||||
|
g = (g << 4) | g;
|
||||||
|
b = (b << 4) | b;
|
||||||
|
|
||||||
|
fullHex = (r << 16) | (g << 8) | b;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case (6, ColorType.CssHexColor):
|
||||||
|
color = new Color(parsedValue);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
case (8, ColorType.CssHexColor):
|
||||||
|
parsedValue &= 0xFFFFFF;
|
||||||
|
color = new Color(parsedValue);
|
||||||
|
return true;
|
||||||
|
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
color = new Color(fullHex);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
public override bool Equals(object obj)
|
public override bool Equals(object obj)
|
||||||
=> obj is Color c && RawValue == c.RawValue;
|
=> obj is Color c && RawValue == c.RawValue;
|
||||||
|
|
||||||
|
|||||||
21
src/Discord.Net.Core/Entities/Roles/ColorType.cs
Normal file
21
src/Discord.Net.Core/Entities/Roles/ColorType.cs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace Discord;
|
||||||
|
|
||||||
|
public enum ColorType
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Color in one of the following formats.
|
||||||
|
/// <para>
|
||||||
|
/// #RGB The three-value syntax
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// #RGBA The four-value syntax
|
||||||
|
/// </para>
|
||||||
|
/// <para>
|
||||||
|
/// #RRGGBB The six-value syntax
|
||||||
|
/// </para>
|
||||||
|
/// #RRGGBBAA The eight-value syntax
|
||||||
|
/// </summary>
|
||||||
|
CssHexColor = 0
|
||||||
|
}
|
||||||
@@ -74,6 +74,26 @@ namespace Discord
|
|||||||
Assert.Throws<ArgumentOutOfRangeException>(() => new Color(2.0f, 2.0f, 2.0f));
|
Assert.Throws<ArgumentOutOfRangeException>(() => new Color(2.0f, 2.0f, 2.0f));
|
||||||
}
|
}
|
||||||
[Fact]
|
[Fact]
|
||||||
|
public void Color_FromRgb_String_CssHexColor()
|
||||||
|
{
|
||||||
|
Assert.Equal(0xFF0000u, Color.Parse("#F00", ColorType.CssHexColor).RawValue);
|
||||||
|
Assert.Equal(0x22BB44u, Color.Parse("#2B4", ColorType.CssHexColor).RawValue);
|
||||||
|
Assert.Equal(0xAABBAAu, Color.Parse("FABA", ColorType.CssHexColor).RawValue);
|
||||||
|
Assert.Equal(0x00F672u, Color.Parse("00F672", ColorType.CssHexColor).RawValue);
|
||||||
|
Assert.Equal(0x257777u, Color.Parse("0xFF257777", ColorType.CssHexColor).RawValue);
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
|
public void Color_FromRgb_String_Invalid()
|
||||||
|
{
|
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => Color.Parse(" ", ColorType.CssHexColor));
|
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => Color.Parse(null, ColorType.CssHexColor));
|
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => Color.Parse("#F"));
|
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => Color.Parse("F0", ColorType.CssHexColor));
|
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => Color.Parse("FF000"));
|
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => Color.Parse("FF00000"));
|
||||||
|
Assert.Throws<ArgumentOutOfRangeException>(() => Color.Parse("FF0000000"));
|
||||||
|
}
|
||||||
|
[Fact]
|
||||||
public void Color_Red()
|
public void Color_Red()
|
||||||
{
|
{
|
||||||
Assert.Equal(0xAF, new Color(0xAF1390).R);
|
Assert.Equal(0xAF, new Color(0xAF1390).R);
|
||||||
|
|||||||
Reference in New Issue
Block a user