2019-05-13 15:04:28 +00:00
|
|
|
use nom::bytes::complete::{tag, take_while_m_n};
|
|
|
|
use nom::combinator::map_res;
|
|
|
|
use nom::sequence::tuple;
|
2020-04-10 09:01:58 +00:00
|
|
|
use nom::IResult;
|
2019-05-13 15:04:28 +00:00
|
|
|
|
2018-02-17 14:06:43 +00:00
|
|
|
#[derive(Debug, PartialEq)]
|
2018-02-11 20:50:04 +00:00
|
|
|
pub struct Color {
|
2018-02-25 12:12:11 +00:00
|
|
|
pub red: u8,
|
2018-02-11 20:50:04 +00:00
|
|
|
pub green: u8,
|
2018-02-25 12:12:11 +00:00
|
|
|
pub blue: u8,
|
2018-02-11 20:50:04 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn from_hex(input: &str) -> Result<u8, std::num::ParseIntError> {
|
|
|
|
u8::from_str_radix(input, 16)
|
|
|
|
}
|
|
|
|
|
|
|
|
fn is_hex_digit(c: char) -> bool {
|
2018-09-24 19:05:19 +00:00
|
|
|
c.is_digit(16)
|
2018-02-11 20:50:04 +00:00
|
|
|
}
|
|
|
|
|
2019-05-13 15:04:28 +00:00
|
|
|
fn hex_primary(input: &str) -> IResult<&str, u8> {
|
2020-04-10 09:01:58 +00:00
|
|
|
map_res(take_while_m_n(2, 2, is_hex_digit), from_hex)(input)
|
2019-05-13 15:04:28 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
fn hex_color(input: &str) -> IResult<&str, Color> {
|
|
|
|
let (input, _) = tag("#")(input)?;
|
|
|
|
let (input, (red, green, blue)) = tuple((hex_primary, hex_primary, hex_primary))(input)?;
|
|
|
|
|
|
|
|
Ok((input, Color { red, green, blue }))
|
|
|
|
}
|
|
|
|
|
2018-02-11 20:50:04 +00:00
|
|
|
#[test]
|
|
|
|
fn parse_color() {
|
2018-02-17 14:06:43 +00:00
|
|
|
assert_eq!(
|
|
|
|
hex_color("#2F14DF"),
|
|
|
|
Ok((
|
|
|
|
"",
|
|
|
|
Color {
|
2018-02-25 12:12:11 +00:00
|
|
|
red: 47,
|
2018-02-17 14:06:43 +00:00
|
|
|
green: 20,
|
2018-02-25 12:12:11 +00:00
|
|
|
blue: 223,
|
2018-02-17 14:06:43 +00:00
|
|
|
}
|
|
|
|
))
|
|
|
|
);
|
2018-02-11 20:50:04 +00:00
|
|
|
}
|