vkfetch_rs/
vendor.rs

1use crate::{ascii_art::*, is_ansi_supported};
2
3/// Represents a GPU vendor.
4#[derive(Debug, Clone, Copy, PartialEq, Eq)]
5pub enum Vendor {
6    AMD = 0x1002,
7    ImgTec = 0x1010,
8    Apple = 0x106B,
9    Nvidia = 0x10DE,
10    ARM = 0x13B5,
11    Microsoft = 0x1414,
12    Google = 0x1AE0,
13    Qualcomm = 0x5143,
14    Intel = 0x8086,
15    Unknown = 0xFFFF,
16    VIV = 0x10001,
17    VSI = 0x10002,
18    Kazan = 0x10003,
19    Codeplay = 0x10004,
20    Mesa = 0x10005,
21    Pocl = 0x10006,
22    MobileEye = 0x10007,
23}
24
25const BLOCK: &str = "\x1B[7m \x1B[0m";
26
27impl Vendor {
28    /// Returns the vendor-specific ASCII art with color styling applied.
29    pub fn get_ascii_art(&self) -> Vec<String> {
30        let art: &[&str] = match self {
31            Vendor::AMD => AMD,
32            Vendor::Apple => APPLE,
33            Vendor::ARM => ARM,
34            Vendor::Google => GOOGLE,
35            Vendor::Intel => INTEL,
36            Vendor::Nvidia => NVIDIA,
37            Vendor::Microsoft => MICROSOFT,
38            Vendor::Qualcomm => QUALCOMM,
39            Vendor::Mesa => VULKAN,
40            Vendor::Unknown
41            | Vendor::ImgTec
42            | Vendor::VIV
43            | Vendor::VSI
44            | Vendor::Kazan
45            | Vendor::Codeplay
46            | Vendor::Pocl
47            | Vendor::MobileEye => VULKAN,
48        };
49
50        let style = if is_ansi_supported() {
51            self.get_alternative_style()
52        } else {
53            self.get_style()
54        };
55        let mut modified_art: Vec<String> = art.iter().map(|&line| line.to_string()).collect();
56
57        for (symbol, style) in CHARS.iter().zip(style.iter()) {
58            if !style.is_empty() {
59                modified_art = modified_art
60                    .iter()
61                    .map(|line| line.replace(*symbol, &format!("{}{}", style, BLOCK)))
62                    .collect();
63            }
64        }
65
66        modified_art
67    }
68
69    /// Returns an array of style strings associated with the vendor.
70    pub const fn get_style(&self) -> [&str; LUT_SIZE] {
71        match self {
72            Vendor::AMD => AMD_STYLE,
73            Vendor::Apple => APPLE_STYLE,
74            Vendor::ARM => ARM_STYLE,
75            Vendor::Google => GOOGLE_STYLE,
76            Vendor::Intel => INTEL_STYLE,
77            Vendor::Nvidia => NVIDIA_STYLE,
78            Vendor::Microsoft => MICROSOFT_STYLE,
79            Vendor::Qualcomm => QUALCOMM_STYLE,
80            Vendor::Mesa => VULKAN_STYLE,
81            Vendor::Unknown
82            | Vendor::ImgTec
83            | Vendor::VIV
84            | Vendor::VSI
85            | Vendor::Kazan
86            | Vendor::Codeplay
87            | Vendor::Pocl
88            | Vendor::MobileEye => VULKAN_STYLE,
89        }
90    }
91
92    /// Returns a human-readable name for the vendor.
93    pub const fn name(&self) -> &'static str {
94        match self {
95            Vendor::AMD => "AMD",
96            Vendor::Apple => "Apple",
97            Vendor::ARM => "ARM",
98            Vendor::Codeplay => "Codeplay",
99            Vendor::Google => "Google",
100            Vendor::ImgTec => "ImgTec",
101            Vendor::Intel => "Intel",
102            Vendor::Kazan => "Kazan",
103            Vendor::Mesa => "Mesa",
104            Vendor::MobileEye => "MobileEye",
105            Vendor::Nvidia => "Nvidia",
106            Vendor::Pocl => "Pocl",
107            Vendor::Qualcomm => "Qualcomm",
108            Vendor::Unknown => "Unknown",
109            Vendor::VIV => "VIV",
110            Vendor::VSI => "VSI",
111            Vendor::Microsoft => "Microsoft",
112        }
113    }
114
115    /// Constructs a Vendor from a vendor ID, if recognized.
116    pub fn from_vendor_id(id: u32) -> Option<Self> {
117        match id {
118            0x1002 => Some(Vendor::AMD),
119            0x1010 => Some(Vendor::ImgTec),
120            0x106B => Some(Vendor::Apple),
121            0x10DE => Some(Vendor::Nvidia),
122            0x13B5 => Some(Vendor::ARM),
123            0x1414 => Some(Vendor::Microsoft),
124            0x1AE0 => Some(Vendor::Google),
125            0x5143 => Some(Vendor::Qualcomm),
126            0x8086 => Some(Vendor::Intel),
127            0xFFFF => Some(Vendor::Unknown),
128            0x10001 => Some(Vendor::VIV),
129            0x10002 => Some(Vendor::VSI),
130            0x10003 => Some(Vendor::Kazan),
131            0x10004 => Some(Vendor::Codeplay),
132            0x10005 => Some(Vendor::Mesa),
133            0x10006 => Some(Vendor::Pocl),
134            0x10007 => Some(Vendor::MobileEye),
135            _ => None,
136        }
137    }
138
139    pub const fn get_alternative_style(&self) -> [&str; LUT_SIZE] {
140        match self {
141            Vendor::AMD => AMD_STYLE_ALT,
142            Vendor::Apple => APPLE_STYLE_ALT,
143            Vendor::ARM => ARM_STYLE_ALT,
144            Vendor::Google => GOOGLE_STYLE_ALT,
145            Vendor::Intel => INTEL_STYLE_ALT,
146            Vendor::Nvidia => NVIDIA_STYLE_ALT,
147            Vendor::Microsoft => MICROSOFT_STYLE_ALT,
148            Vendor::Qualcomm => QUALCOMM_STYLE_ALT,
149            Vendor::Mesa => VULKAN_STYLE_ALT,
150            Vendor::Unknown
151            | Vendor::ImgTec
152            | Vendor::VIV
153            | Vendor::VSI
154            | Vendor::Kazan
155            | Vendor::Codeplay
156            | Vendor::Pocl
157            | Vendor::MobileEye => VULKAN_STYLE_ALT,
158        }
159    }
160}
161
162impl From<Vendor> for u32 {
163    fn from(v: Vendor) -> Self {
164        v as u32
165    }
166}
167
168/// Allows a vendor to be printed using its human‑readable name.
169impl std::fmt::Display for Vendor {
170    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
171        write!(f, "{}", self.name())
172    }
173}
174
175#[cfg(test)]
176mod tests {
177    use super::*;
178
179    #[test]
180    fn test_from_vendor_id() {
181        assert_eq!(Vendor::from_vendor_id(0x1002), Some(Vendor::AMD));
182        assert_eq!(Vendor::from_vendor_id(0x1010), Some(Vendor::ImgTec));
183        assert_eq!(Vendor::from_vendor_id(0x10DE), Some(Vendor::Nvidia));
184        assert_eq!(Vendor::from_vendor_id(0x9999), None);
185    }
186
187    #[test]
188    fn test_name() {
189        assert_eq!(Vendor::AMD.name(), "AMD");
190        assert_eq!(Vendor::Apple.name(), "Apple");
191        assert_eq!(Vendor::Intel.name(), "Intel");
192        assert_eq!(Vendor::Unknown.name(), "Unknown");
193    }
194
195    #[test]
196    fn test_display() {
197        let vendor = Vendor::Nvidia;
198        let s = format!("{}", vendor);
199        assert_eq!(s, vendor.name());
200    }
201
202    #[test]
203    fn test_get_styles_length() {
204        let vendor = Vendor::AMD;
205        let styles = vendor.get_style();
206        assert_eq!(styles.len(), crate::ascii_art::LUT_SIZE);
207    }
208
209    #[test]
210    fn test_get_ascii_art() {
211        let vendor = Vendor::AMD;
212        let art = vendor.get_ascii_art();
213        assert!(!art.is_empty(), "ASCII art should not be empty");
214
215        let styles = vendor.get_style();
216        let non_empty_style = styles.iter().any(|s| !s.is_empty());
217        if non_empty_style {
218            let block_found = art.iter().any(|line| line.contains(BLOCK));
219            assert!(block_found, "Styled block should appear in ASCII art lines");
220        }
221    }
222}