Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
104 changes: 102 additions & 2 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1799,8 +1799,35 @@ impl ColorSpec {
/// 2. A single 8-bit integer, in either decimal or hexadecimal format.
/// 3. A triple of 8-bit integers separated by a comma, where each integer is
/// in decimal or hexadecimal format.
/// 4. A `#` followed by 6 hexadecimal digits of any case, with each octet
/// representing red, green and blue, respectively.
///
/// Hexadecimal numbers are written with a `0x` prefix.
///
/// ## Example
/// ```
/// use termcolor::Color;
///
/// let color = "red".parse::<Color>();
/// assert_eq!(color, Ok(Color::Red));
///
/// let color = "32".parse::<Color>();
/// assert_eq!(color, Ok(Color::Ansi256(32)));
///
/// // Note that also lowercase 0xaa is allowed
/// let color = "0xAA".parse::<Color>();
/// assert_eq!(color, Ok(Color::Ansi256(0xAA)));
///
/// let color = "0,128,255".parse::<Color>();
/// assert_eq!(color, Ok(Color::Rgb(0, 128, 255)));
///
/// let color = "0x0,0xFF,0x0".parse::<Color>();
/// assert_eq!(color, Ok(Color::Rgb(0, 0xFF, 0)));
///
/// // Note that also lowercase #ff6633 is allowed
/// let color = "#FF6633".parse::<Color>();
/// assert_eq!(color, Ok(Color::Rgb(0xFF, 0x66, 0x33)));
/// ```
#[allow(missing_docs)]
#[derive(Clone, Copy, Debug, Eq, PartialEq)]
pub enum Color {
Expand Down Expand Up @@ -1866,7 +1893,8 @@ impl Color {
// corresponding to one of 256 colors.
//
// The "rgb" format is a triple of numbers (decimal or hex) delimited
// by a comma corresponding to one of 256^3 colors.
// by a comma corresponding to one of 256^3 colors or #rrggbb string
// in the hex format.

fn parse_number(s: &str) -> Option<u8> {
use std::u8;
Expand All @@ -1880,7 +1908,22 @@ impl Color {

let codes: Vec<&str> = s.split(',').collect();
if codes.len() == 1 {
if let Some(n) = parse_number(&codes[0]) {
if codes[0].starts_with('#') {
use std::u8;
if codes[0].len() == 7 {
if let (Ok(r), Ok(g), Ok(b)) = (
u8::from_str_radix(&codes[0][1..3], 16),
u8::from_str_radix(&codes[0][3..5], 16),
u8::from_str_radix(&codes[0][5..7], 16),
) {
return Ok(Color::Rgb(r, g, b));
}
}
Err(ParseColorError {
kind: ParseColorErrorKind::InvalidRgb,
given: s.to_string(),
})
} else if let Some(n) = parse_number(&codes[0]) {
Ok(Color::Ansi256(n))
} else {
if s.chars().all(|c| c.is_digit(16)) {
Expand Down Expand Up @@ -2137,6 +2180,18 @@ mod tests {

let color = "0x33,0x66,0xFF".parse::<Color>();
assert_eq!(color, Ok(Color::Rgb(0x33, 0x66, 0xFF)));

let color = "0xCC,0xaa,0xff".parse::<Color>();
assert_eq!(color, Ok(Color::Rgb(0xCC, 0xAA, 0xFF)));

let color = "0xCC,0xaa,0xff".parse::<Color>();
assert_eq!(color, Ok(Color::Rgb(0xCC, 0xAA, 0xFF)));

let color = "#FF6633".parse::<Color>();
assert_eq!(color, Ok(Color::Rgb(0xFF, 0x66, 0x33)));

let color = "#ffCCaa".parse::<Color>();
assert_eq!(color, Ok(Color::Rgb(0xFF, 0xCC, 0xAA)));
}

#[test]
Expand All @@ -2149,6 +2204,15 @@ mod tests {
given: "0,0,256".to_string(),
})
);

let color = "0,0,aaa".parse::<Color>();
assert_eq!(
color,
Err(ParseColorError {
kind: ParseColorErrorKind::InvalidRgb,
given: "0,0,aaa".to_string(),
})
);
}

#[test]
Expand All @@ -2162,6 +2226,24 @@ mod tests {
})
);

let color = "#ffCC001".parse::<Color>();
assert_eq!(
color,
Err(ParseColorError {
kind: ParseColorErrorKind::InvalidRgb,
given: "#ffCC001".to_string()
})
);

let color = "#00CC1".parse::<Color>();
assert_eq!(
color,
Err(ParseColorError {
kind: ParseColorErrorKind::InvalidRgb,
given: "#00CC1".to_string()
})
);

let color = "not_a_color".parse::<Color>();
assert_eq!(
color,
Expand All @@ -2170,6 +2252,24 @@ mod tests {
given: "not_a_color".to_string(),
})
);

let color = "#00ggee".parse::<Color>();
assert_eq!(
color,
Err(ParseColorError {
kind: ParseColorErrorKind::InvalidRgb,
given: "#00ggee".to_string(),
})
);

let color = "#00gg😜".parse::<Color>();
assert_eq!(
color,
Err(ParseColorError {
kind: ParseColorErrorKind::InvalidRgb,
given: "#00gg😜".to_string(),
})
);
}

#[test]
Expand Down