use crate::{css, types::*, Color};
#[derive(Copy, Clone, Debug, PartialEq)]
pub struct Hsva {
pub h: f64,
pub s: f64,
pub v: f64,
pub alpha: f64,
}
impl Color for Hsva {
fn hex(&self) -> String {
Rgba::from(*self).hex()
}
}
impl Eq for Hsva {}
#[allow(clippy::derive_hash_xor_eq)]
impl std::hash::Hash for Hsva {
fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
self.h.to_bits().hash(state);
self.s.to_bits().hash(state);
self.v.to_bits().hash(state);
self.alpha.to_bits().hash(state);
}
}
impl From<[f64; 4]> for Hsva {
fn from(array: [f64; 4]) -> Self {
Self {
h: array[0],
s: array[1],
v: array[2],
alpha: array[3],
}
}
}
impl From<Hsva> for [f64; 4] {
fn from(color: Hsva) -> Self {
[color.h, color.s, color.v, color.alpha]
}
}
impl From<Rgb> for Hsva {
fn from(other: Rgb) -> Self {
Self::from(Hsv::from(other))
}
}
impl From<Hsv> for Hsva {
fn from(other: Hsv) -> Self {
Self {
h: other.h,
s: other.s,
v: other.v,
alpha: 1.0,
}
}
}
impl From<Hsl> for Hsva {
fn from(other: Hsl) -> Self {
Self::from(Hsv::from(other))
}
}
impl From<Rgba> for Hsva {
fn from(other: Rgba) -> Self {
let Hsv { h, s, v } = Hsv::from(other);
Self {
h,
s,
v,
alpha: other.alpha,
}
}
}
impl From<Hsla> for Hsva {
fn from(other: Hsla) -> Self {
let Hsv { h, s, v } = Hsv::from(other);
Self {
h,
s,
v,
alpha: other.alpha,
}
}
}
impl TryFrom<&css::CssColorNotation> for Hsva {
type Error = css::Error;
fn try_from(other: &css::CssColorNotation) -> css::Result<Self> {
match other.format {
css::CssColorType::Hsv => Ok(Self::from(Hsv::try_from(other)?)),
css::CssColorType::Hsva => {
let mut this = Self::from(Hsv::try_from(other)?);
this.alpha = css::css_number_to_float(
other.values.get(3).ok_or(css::Error::InvalidCssParams)?,
);
Ok(this)
}
_ => Err(css::Error::WrongCssFormat),
}
}
}
impl From<Hsva> for css::CssColorNotation {
fn from(other: Hsva) -> Self {
Self {
format: css::CssColorType::Hsva,
values: vec![
css::CssNumber::Float(other.h),
css::CssNumber::Percent(other.s),
css::CssNumber::Percent(other.v),
css::CssNumber::Percent(other.alpha),
],
}
}
}