reddit-rs 0.1.1

A wrapper around the Reddit API.
Documentation
use std::ops::Range;

use serde::{de::Unexpected, Deserialize, Deserializer, Serialize};

#[derive(Debug, Clone, Copy, Serialize, Deserialize, PartialEq)]
pub enum Color {
    Transparent,
    Rgb { r: u8, g: u8, b: u8 },
}

impl Color {
    pub(crate) fn from_hex_str<'de, D>(deserializer: D) -> Result<Option<Self>, D::Error>
    where
        D: Deserializer<'de>,
    {
        fn get_rgb_value<'de, D: Deserializer<'de>>(
            hex: &str,
            range: Range<usize>,
        ) -> Result<u8, <D as Deserializer<'de>>::Error> {
            use serde::de::Error;

            let value = if let Some(value) = hex
                .get(range)
                .and_then(|val| u8::from_str_radix(val, 16).ok())
            {
                value
            } else {
                return Err(D::Error::invalid_value(
                    Unexpected::Other("non-hex string"),
                    &"hex string of format #RRGGBB",
                ));
            };
            Ok(value)
        }

        let hex = match Option::<String>::deserialize(deserializer) {
            Ok(Some(s)) if s == "transparent" => return Ok(Some(Self::Transparent)),
            Ok(Some(hex)) => hex,
            Ok(None) => return Ok(None),
            Err(why) => return Err(why),
        };

        if hex.is_empty() {
            return Ok(None);
        }

        Ok(Some(Self::Rgb {
            r: get_rgb_value::<D>(&hex, 1..3)?,
            g: get_rgb_value::<D>(&hex, 3..5)?,
            b: get_rgb_value::<D>(&hex, 5..7)?,
        }))
    }
}