1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
use super::converters::hex_num_to_rgb;
use super::error::{
  make_def_parse_err, make_hex_parse_err, make_hsl_parse_err, make_hsla_parse_err,
  make_rgb_parse_err, make_rgba_parse_err, ParseError,
};
use super::{ColorTuple, ColorTupleA};

pub fn hex(s: &str) -> Result<ColorTuple, ParseError> {
  let mut hex = s.replace("#", "").to_lowercase();
  let count = hex.chars().count();

  if count == 3 {
    hex = hex.chars().map(|c| c.to_string().repeat(2)).collect::<Vec<String>>().join("");
  } else if count != 6 {
    return Err(make_hex_parse_err(s));
  }

  match usize::from_str_radix(&hex, 16) {
    Ok(num) => Ok(hex_num_to_rgb(num)),
    Err(_) => Err(make_hex_parse_err(s)),
  }
}

fn clear_str(s: &str) -> String {
  let mut result = s.to_lowercase();
  for p in ["rgba", "rgb", "hsla", "hsl", "(", ")", "%", " "].iter() {
    result = result.replace(p, "");
  }
  result
}

fn collect_vec_and_parse(s: &str) -> Result<Vec<f32>, std::num::ParseFloatError> {
  let v = s.split(',').map(|c| c.to_string()).collect::<Vec<String>>();

  let mut units = Vec::new();

  for unit in v {
    let u = unit.parse::<f32>()?;
    units.push(u);
  }

  Ok(units)
}

fn parse_color_tuple(s: &str) -> Result<ColorTuple, ParseError> {
  match collect_vec_and_parse(&clear_str(s)) {
    Ok(num_vec) => {
      if num_vec.len() != 3 {
        Err(make_def_parse_err(&s))
      } else {
        Ok((num_vec[0], num_vec[1], num_vec[2]))
      }
    }
    Err(_) => Err(make_def_parse_err(&s)),
  }
}

fn parse_color_tuple_a(s: &str) -> Result<ColorTupleA, ParseError> {
  match collect_vec_and_parse(&clear_str(s)) {
    Ok(num_vec) => {
      if num_vec.len() != 4 {
        Err(make_def_parse_err(&s))
      } else {
        Ok((num_vec[0], num_vec[1], num_vec[2], num_vec[3]))
      }
    }
    Err(_) => Err(make_def_parse_err(&s)),
  }
}

pub fn rgb(s: &str) -> Result<ColorTuple, ParseError> {
  match parse_color_tuple(s) {
    Err(_) => Err(make_rgb_parse_err(s)),
    Ok(rgb) => Ok(rgb),
  }
}

pub fn rgba(s: &str) -> Result<ColorTupleA, ParseError> {
  match parse_color_tuple_a(s) {
    Err(_) => Err(make_rgba_parse_err(s)),
    Ok(rgba) => Ok(rgba),
  }
}

pub fn hsl(s: &str) -> Result<ColorTuple, ParseError> {
  match parse_color_tuple(s) {
    Err(_) => Err(make_hsl_parse_err(s)),
    Ok(hsl) => Ok(hsl),
  }
}

pub fn hsla(s: &str) -> Result<ColorTupleA, ParseError> {
  match parse_color_tuple_a(s) {
    Err(_) => Err(make_hsla_parse_err(s)),
    Ok(hsla) => Ok(hsla),
  }
}