1 extern crate nom;
2
3 use nom::IResult;
4 use nom::bytes::complete::{tag, take_while_m_n};
5 use nom::combinator::map_res;
6 use nom::sequence::tuple;
7
8 #[derive(Debug, PartialEq)]
9 pub struct Color {
10 pub red: u8,
11 pub green: u8,
12 pub blue: u8,
13 }
14
from_hex(input: &str) -> Result<u8, std::num::ParseIntError>15 fn from_hex(input: &str) -> Result<u8, std::num::ParseIntError> {
16 u8::from_str_radix(input, 16)
17 }
18
is_hex_digit(c: char) -> bool19 fn is_hex_digit(c: char) -> bool {
20 c.is_digit(16)
21 }
22
hex_primary(input: &str) -> IResult<&str, u8>23 fn hex_primary(input: &str) -> IResult<&str, u8> {
24 map_res(
25 take_while_m_n(2, 2, is_hex_digit),
26 from_hex
27 )(input)
28 }
29
hex_color(input: &str) -> IResult<&str, Color>30 fn hex_color(input: &str) -> IResult<&str, Color> {
31 let (input, _) = tag("#")(input)?;
32 let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(input)?;
33
34 Ok((input, Color { red, green, blue }))
35 }
36
37
38 #[test]
parse_color()39 fn parse_color() {
40 assert_eq!(
41 hex_color("#2F14DF"),
42 Ok((
43 "",
44 Color {
45 red: 47,
46 green: 20,
47 blue: 223,
48 }
49 ))
50 );
51 }
52