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