#pragma once
#include <algorithm>
#include <stdexcept>
#include <string>
#include <string_view>
#include <fmt/format.h>
#include <wpi/StringExtras.h>
#include <wpi/ct_string.h>
#include "Color.h"
namespace frc {
class Color8Bit {
public:
constexpr Color8Bit() = default;
constexpr Color8Bit(int r, int g, int b)
: red(std::clamp(r, 0, 255)),
green(std::clamp(g, 0, 255)),
blue(std::clamp(b, 0, 255)) {}
constexpr Color8Bit(const Color& color) : red(color.red * 255),
green(color.green * 255),
blue(color.blue * 255) {}
explicit constexpr Color8Bit(std::string_view hexString) {
if (hexString.length() != 7 || !hexString.starts_with("#") ||
!wpi::isHexDigit(hexString[1]) || !wpi::isHexDigit(hexString[2]) ||
!wpi::isHexDigit(hexString[3]) || !wpi::isHexDigit(hexString[4]) ||
!wpi::isHexDigit(hexString[5]) || !wpi::isHexDigit(hexString[6])) {
throw std::invalid_argument(
fmt::format("Invalid hex string for Color \"{}\"", hexString));
}
red = wpi::hexDigitValue(hexString[1]) * 16 +
wpi::hexDigitValue(hexString[2]);
green = wpi::hexDigitValue(hexString[3]) * 16 +
wpi::hexDigitValue(hexString[4]);
blue = wpi::hexDigitValue(hexString[5]) * 16 +
wpi::hexDigitValue(hexString[6]);
}
constexpr bool operator==(const Color8Bit&) const = default;
constexpr operator Color() const { return Color(red / 255.0, green / 255.0, blue / 255.0);
}
static constexpr Color8Bit FromHexString(std::string_view hexString) {
if (hexString.length() != 7 || !hexString.starts_with("#") ||
!wpi::isHexDigit(hexString[1]) || !wpi::isHexDigit(hexString[2]) ||
!wpi::isHexDigit(hexString[3]) || !wpi::isHexDigit(hexString[4]) ||
!wpi::isHexDigit(hexString[5]) || !wpi::isHexDigit(hexString[6])) {
throw std::invalid_argument(
fmt::format("Invalid hex string for Color \"{}\"", hexString));
}
int r = wpi::hexDigitValue(hexString[0]) * 16 +
wpi::hexDigitValue(hexString[1]);
int g = wpi::hexDigitValue(hexString[2]) * 16 +
wpi::hexDigitValue(hexString[3]);
int b = wpi::hexDigitValue(hexString[4]) * 16 +
wpi::hexDigitValue(hexString[5]);
return Color8Bit{r, g, b};
}
constexpr auto HexString() const {
return wpi::ct_string<char, std::char_traits<char>, 7>{
{'#', wpi::hexdigit(red / 16), wpi::hexdigit(red % 16),
wpi::hexdigit(green / 16), wpi::hexdigit(green % 16),
wpi::hexdigit(blue / 16), wpi::hexdigit(blue % 16)}};
}
int red = 0;
int green = 0;
int blue = 0;
};
}