use crate::cpu::Vendor;
use colored::Color;
#[cfg(feature = "display")]
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum LogoSize {
Short,
Long,
}
#[cfg(feature = "display")]
pub struct LogoColors {
pub colors: [Option<Color>; 4],
}
#[cfg(feature = "display")]
pub fn get_raw_logo(vendor: &Vendor, size: LogoSize) -> &'static str {
match (vendor, size) {
(Vendor::Intel, LogoSize::Long) => INTEL_LOGO_LONG,
(Vendor::Intel, LogoSize::Short) => INTEL_LOGO,
(Vendor::AMD, LogoSize::Long) => AMD_LOGO_LONG,
(Vendor::AMD, LogoSize::Short) => AMD_LOGO,
(Vendor::ARM, LogoSize::Long) => ARM_LOGO_LONG,
(Vendor::ARM, LogoSize::Short) => ARM_LOGO,
(Vendor::Apple, _) => APPLE_LOGO,
(Vendor::Unknown, _) => GENERIC_LOGO,
}
}
#[cfg(feature = "display")]
pub fn get_logo_colors(vendor: &Vendor) -> LogoColors {
match vendor {
Vendor::Intel | Vendor::ARM => LogoColors {
colors: [Some(Color::Cyan), None, None, None],
},
Vendor::AMD => LogoColors {
colors: [Some(Color::White), Some(Color::Green), None, None],
},
Vendor::Apple => LogoColors {
colors: [Some(Color::White), None, None, None],
},
Vendor::Unknown => LogoColors {
colors: [Some(Color::Yellow), None, None, None],
},
}
}
#[cfg(feature = "display")]
#[allow(dead_code)]
pub fn get_text_color(vendor: &Vendor) -> Color {
match vendor {
Vendor::AMD => Color::Green,
Vendor::Intel | Vendor::ARM | Vendor::Apple => Color::Cyan,
Vendor::Unknown => Color::Yellow,
}
}
#[cfg(feature = "display")]
pub fn colorize_logo_line(line: &str, colors: &LogoColors) -> String {
let mut result = String::with_capacity(line.len() * 2);
let mut chars = line.chars().peekable();
while let Some(ch) = chars.next() {
if ch == '$' {
match chars.peek() {
Some('C') => {
chars.next(); match chars.peek() {
Some('R') => {
chars.next(); result.push_str("\x1b[0m");
},
Some(n @ '1'..='4') => {
let idx = (*n as usize) - ('1' as usize);
chars.next(); if let Some(color) = colors.colors[idx] {
result.push_str(&color_to_ansi_bold(color));
}
},
_ => {
result.push('$');
result.push('C');
},
}
},
_ => result.push('$'),
}
} else {
result.push(ch);
}
}
result.push_str("\x1b[0m");
result
}
#[cfg(feature = "display")]
fn color_to_ansi_bold(color: Color) -> String {
match color {
Color::Black => "\x1b[30;1m".to_string(),
Color::Red => "\x1b[31;1m".to_string(),
Color::Green => "\x1b[32;1m".to_string(),
Color::Yellow => "\x1b[33;1m".to_string(),
Color::Blue => "\x1b[34;1m".to_string(),
Color::Magenta => "\x1b[35;1m".to_string(),
Color::Cyan => "\x1b[36;1m".to_string(),
Color::White => "\x1b[37;1m".to_string(),
Color::BrightBlack => "\x1b[90;1m".to_string(),
Color::BrightRed => "\x1b[91;1m".to_string(),
Color::BrightGreen => "\x1b[92;1m".to_string(),
Color::BrightYellow => "\x1b[93;1m".to_string(),
Color::BrightBlue => "\x1b[94;1m".to_string(),
Color::BrightMagenta => "\x1b[95;1m".to_string(),
Color::BrightCyan => "\x1b[96;1m".to_string(),
Color::BrightWhite => "\x1b[97;1m".to_string(),
Color::TrueColor { r, g, b } => format!("\x1b[38;2;{r};{g};{b};1m"),
Color::AnsiColor(n) => format!("\x1b[38;5;{n};1m"),
}
}
#[cfg(feature = "display")]
const AMD_LOGO: &str = "\
$C2 '############### \n\
$C2 ,############# \n\
$C2 .#### \n\
$C2 #. .#### \n\
$C2 :##. .#### \n\
$C2 :###. .#### \n\
$C2 #########. :## \n\
$C2 #######. ; \n\
$C1 \n\
$C1 ### ### ### ####### \n\
$C1 ## ## ##### ##### ## ## \n\
$C1 ## ## ### #### ### ## ##\n\
$C1 ######### ### ## ### ## ##\n\
$C1## ## ### ### ## ## \n\
$C1## ## ### ### ####### ";
#[cfg(feature = "display")]
const INTEL_LOGO: &str = "\
$C1 .#################. \n\
$C1 .#### ####. \n\
$C1 .## ###\n\
$C1 ## :## ##\n\
$C1 # ## :## #\n\
$C1 ## ## ######. #### ###### :## #\n\
$C1 ## ## ##: ##: ## ## ### :## ##\n\
$C1## ## ##: ##: ## :######## :## ## \n\
$C1## ## ##: ##: ## ##. . :## #### \n\
$C1## # ##: ##: #### #####: ## \n\
$C1 ## \n\
$C1 ###. ..o####. \n\
$C1 ######oo... ..oo####### \n\
$C1 o###############o ";
#[cfg(feature = "display")]
const ARM_LOGO: &str = "\
$C1 ##### ## # ##### ## #### ###### \n\
$C1 ### #### ### #### ### ### \n\
$C1### ## ### ### ## ###\n\
$C1 ### #### ### ### ## ###\n\
$C1 ###### ## ### ### ## ###";
#[cfg(feature = "display")]
const APPLE_LOGO: &str = "\
$C1 .\"c. \n\
$C1 ,xNMM. \n\
$C1 .lMM\" \n\
$C1 MM* \n\
$C1 .;loddo;:. olloddol;. \n\
$C1 cKMMMMMMMMMMNWMMMMMMMMMMM0\n\
$C1 .KMMMMMMMMMMMMMMMMMMMMMMMW* \n\
$C1 XMMMMMMMMMMMMMMMMMMMMMMMX. \n\
$C1;MMMMMMMMMMMMMMMMMMMMMMMM: \n\
$C1:MMMMMMMMMMMMMMMMMMMMMMMM: \n\
$C1.MMMMMMMMMMMMMMMMMMMMMMMMX. \n\
$C1 kMMMMMMMMMMMMMMMMMMMMMMMMWd.\n\
$C1 'XMMMMMMMMMMMMMMMMMMMMMMMMM \n\
$C1 'XMMMMMMMMMMMMMMMMMMMMMMK. \n\
$C1 kMMMMMMMMMMMMMMMMMMMMd \n\
$C1 'KMMMMMMMWXXWMMMMMk. \n\
$C1 \"cooc\"* \"*coo'\" ";
#[cfg(feature = "display")]
const GENERIC_LOGO: &str = "\
$C1 /---------\\\n\
$C1 | CPU |\n\
$C1 \\---------/";
#[cfg(feature = "display")]
const AMD_LOGO_LONG: &str = "\
$C1 \n\
$C1 \n\
$C1 \n\
$C1 \n\
$C1 \n\
$C1 \n\
$C1 @@@@ @@@ @@@ @@@@@@@@ $C2 ############\n\
$C1 @@@@@@ @@@@@ @@@@@ @@@ @@@ $C2 ##########\n\
$C1 @@@ @@@ @@@@@@@@@@@@@ @@@ @@ $C2 # #####\n\
$C1 @@@ @@@ @@@ @@@ @@@ @@@ @@ $C2 ### #####\n\
$C1 @@@@@@@@@@@@ @@@ @@@ @@@ @@@ $C2######### ###\n\
$C1 @@@ @@@ @@@ @@@ @@@@@@@@@ $C2######## ##\n\
$C1 \n\
$C1 \n\
$C1 \n\
$C1 \n\
$C1 \n\
$C1 \n\
$C1 ";
#[cfg(feature = "display")]
const INTEL_LOGO_LONG: &str = "\
$C1 ###############@ \n\
$C1 ######@ ######@ \n\
$C1 ###@ ###@ \n\
$C1 ##@ ###@ \n\
$C1 ##@ ##\n\
$C1 ##@ ##\n\
$C1 @ ##@ ##@ ##\n\
$C1 #@ ##@ ########@ #####@ #####@ ##@ ##\n\
$C1 #@ ##@ ##@ ##@ ##@ ###@ ###@ ##@ ##\n\
$C1 #@ ##@ ##@ ##@ ##@ ##@ ##@ ##@ ## \n\
$C1 #@ ##@ ##@ ##@ ##@ #########@ ##@ ### \n\
$C1 #@ ##@ ##@ ##@ ##@ ##@ ##@ #### \n\
$C1 #@ #@ ##@ ##@ ####@ ########@ #@ ## \n\
$C1 ##@ \n\
$C1 ##@ \n\
$C1 ###@ ###@ \n\
$C1 ####@ #########@ \n\
$C1 #########@ ###############@ \n\
$C1 ##############################@ ";
#[cfg(feature = "display")]
const ARM_LOGO_LONG: &str = "\
$C1 ############ ########## #### ####### ########\n\
$C1 ############### ######### #######################\n\
$C1 #### #### #### ##### ######## ####\n\
$C1#### #### #### #### ###### ###\n\
$C1#### #### #### #### #### ###\n\
$C1 #### ##### #### #### #### ###\n\
$C1 ############### #### #### #### ###\n\
$C1 ######## #### #### #### #### ###";
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_colorize_logo_line_single_color() {
let colors = LogoColors {
colors: [Some(Color::Cyan), None, None, None],
};
let line = "$C1Hello World";
let result = colorize_logo_line(line, &colors);
assert!(result.contains("Hello World"));
assert!(result.contains("\x1b[36;1m")); assert!(result.ends_with("\x1b[0m")); }
#[test]
fn test_colorize_logo_line_two_colors() {
let colors = LogoColors {
colors: [Some(Color::White), Some(Color::Green), None, None],
};
let line = "$C1White part$C2Green part";
let result = colorize_logo_line(line, &colors);
assert!(result.contains("\x1b[37;1m")); assert!(result.contains("\x1b[32;1m")); }
#[test]
fn test_colorize_logo_line_with_reset() {
let colors = LogoColors {
colors: [Some(Color::Red), None, None, None],
};
let line = "$C1Red$CR Normal$C1Red again";
let result = colorize_logo_line(line, &colors);
assert_eq!(result.matches("\x1b[31;1m").count(), 2);
assert!(result.contains("\x1b[0m"));
}
#[test]
fn test_get_raw_logo_fallback() {
let short = get_raw_logo(&Vendor::Apple, LogoSize::Short);
let long = get_raw_logo(&Vendor::Apple, LogoSize::Long);
assert_eq!(short, long);
}
#[test]
fn test_logo_line_counts() {
assert_eq!(get_raw_logo(&Vendor::AMD, LogoSize::Short).lines().count(), 15);
assert_eq!(get_raw_logo(&Vendor::Intel, LogoSize::Short).lines().count(), 14);
assert_eq!(get_raw_logo(&Vendor::ARM, LogoSize::Short).lines().count(), 5);
assert_eq!(get_raw_logo(&Vendor::Apple, LogoSize::Short).lines().count(), 17);
assert_eq!(get_raw_logo(&Vendor::AMD, LogoSize::Long).lines().count(), 19);
assert_eq!(get_raw_logo(&Vendor::Intel, LogoSize::Long).lines().count(), 19);
assert_eq!(get_raw_logo(&Vendor::ARM, LogoSize::Long).lines().count(), 8);
}
}