irospace 0.1.0

color space and conversion method
Documentation
use std::marker::PhantomData;

use crate::converter::*;
use crate::hsl::HslColor;
use crate::hsv::HsvColor;
use crate::rgb::RgbColor;

pub struct ColorConverterBuilder {}
pub struct ColorConverterFromBuilder<TFrom>(PhantomData<TFrom>);
pub struct ColorConverterFromToBuilder<TFrom, TTo>(PhantomData<TFrom>, PhantomData<TTo>);

pub struct HtmlConverterFromBuilder {}

pub struct HtmlConverterFromToBuilder<TTo>(PhantomData<TTo>);

impl ColorConverterBuilder {
    pub fn new() -> Self {
        ColorConverterBuilder {}
    }

    pub fn from_rgb(&self) -> ColorConverterFromBuilder<RgbColor> {
        ColorConverterFromBuilder(PhantomData)
    }

    pub fn from_hsv(&self) -> ColorConverterFromBuilder<HsvColor> {
        ColorConverterFromBuilder(PhantomData)
    }

    pub fn from_hsl(&self) -> ColorConverterFromBuilder<HslColor> {
        ColorConverterFromBuilder(PhantomData)
    }

    pub fn from_html(&self) -> HtmlConverterFromBuilder {
        HtmlConverterFromBuilder {}
    }
}

impl HtmlConverterFromBuilder {
    pub fn to_rgb(&self) -> ColorConverterFromToBuilder<HtmlColorCode, RgbColor> {
        ColorConverterFromToBuilder(PhantomData, PhantomData)
    }

    pub fn to_hsv(&self) -> ColorConverterFromToBuilder<HtmlColorCode, HsvColor> {
        ColorConverterFromToBuilder(PhantomData, PhantomData)
    }

    pub fn to_hsl(&self) -> ColorConverterFromToBuilder<HtmlColorCode, HslColor> {
        ColorConverterFromToBuilder(PhantomData, PhantomData)
    }
}

#[allow(unused_macros)]
macro_rules! color_from_builder {
    ($from_name: ident) => {
        impl ColorConverterFromBuilder<$from_name> {
            pub fn to_rgb(&self) -> ColorConverterFromToBuilder<$from_name, RgbColor> {
                ColorConverterFromToBuilder(PhantomData, PhantomData)
            }

            pub fn to_hsv(&self) -> ColorConverterFromToBuilder<$from_name, HsvColor> {
                ColorConverterFromToBuilder(PhantomData, PhantomData)
            }

            pub fn to_hsl(&self) -> ColorConverterFromToBuilder<$from_name, HslColor> {
                ColorConverterFromToBuilder(PhantomData, PhantomData)
            }

            pub fn to_html(&self) -> ColorConverterFromToBuilder<$from_name, HtmlColorCode> {
                ColorConverterFromToBuilder(PhantomData, PhantomData)
            }
        }
    };
}

#[allow(unused_macros)]
macro_rules! color_from_to_builder {
    ($converter_name: ident, $from_name: ident, $to_name: ident) => {
        impl ColorConverterFromToBuilder<$from_name, $to_name> {
            #[allow(dead_code)]
            pub fn build(&self) -> $converter_name {
                $converter_name {}
            }
        }
    };
}

color_from_builder!(RgbColor);
color_from_builder!(HsvColor);
color_from_builder!(HslColor);

color_from_to_builder!(RgbToRgbConverter, RgbColor, RgbColor);
color_from_to_builder!(RgbToHsvConverter, RgbColor, HsvColor);
color_from_to_builder!(RgbToHslConverter, RgbColor, HslColor);

color_from_to_builder!(HsvToRgbConverter, HsvColor, RgbColor);
color_from_to_builder!(HsvToHsvConverter, HsvColor, HsvColor);
color_from_to_builder!(HsvToHslConverter, HsvColor, HslColor);

color_from_to_builder!(HslToRgbConverter, HslColor, RgbColor);
color_from_to_builder!(HslToHsvConverter, HslColor, HsvColor);
color_from_to_builder!(HslToHslConverter, HslColor, HslColor);

color_from_to_builder!(HtmlToRgbConverter, HtmlColorCode, RgbColor);
color_from_to_builder!(HtmlToHsvConverter, HtmlColorCode, HsvColor);
color_from_to_builder!(HtmlToHslConverter, HtmlColorCode, HslColor);

color_from_to_builder!(RgbToHtmlConverter, RgbColor, HtmlColorCode);
color_from_to_builder!(HslToHtmlConverter, HsvColor, HtmlColorCode);
color_from_to_builder!(HsvToHtmlConverter, HslColor, HtmlColorCode);

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn color_build_new_test() {
        let converter = ColorConverterBuilder::new().from_rgb().to_hsv().build();
        assert_eq!(
            converter.convert(&RgbColor::new(255, 0, 0)).unwrap(),
            HsvColor::new(0, 100, 100)
        );
    }

    #[test]
    fn color_build_new_test2() {
        let converter = ColorConverterBuilder::new().from_rgb().to_html().build();
        assert_eq!(
            converter.convert(&RgbColor::new(255, 0, 0)).unwrap(),
            HtmlColorCode::new("#ff0000")
        );
    }

    #[test]
    fn color_build_new_test3() {
        let converter = ColorConverterBuilder::new().from_html().to_rgb().build();
        assert_eq!(
            converter.convert(&HtmlColorCode::new("#ff0000")).unwrap(),
            RgbColor::new(255, 0, 0)
        );
    }
}