sysmonk/legacy/
gpu.rs

1use crate::squire;
2use serde_json::Value;
3use std::collections::HashMap;
4
5/// Function to get GPU information for macOS machines.
6///
7/// # Arguments
8///
9/// * `lib_path` - The path to the library used to get GPU information.
10///
11/// # Returns
12///
13/// A `Vec` of `HashMap` containing GPU(s) information if successful, otherwise an empty `Vec`.
14fn get_gpu_info_darwin(lib_path: &str) -> Vec<HashMap<String, String>> {
15    let result: Result<String, String> = squire::util::run_command(
16        lib_path,
17        &["SPDisplaysDataType", "-json"],
18        true,
19    );
20    let displays: Vec<Value>;
21    match result {
22        Ok(json_str) => {
23            match serde_json::from_str::<Value>(&json_str) {
24                Ok(json) => {
25                    if let Some(d) = json.get("SPDisplaysDataType").and_then(Value::as_array) {
26                        displays = d.to_vec();
27                    } else {
28                        log::error!("Key 'SPDisplaysDataType' not found or is not an array.");
29                        return Vec::new();
30                    }
31                }
32                Err(err) => {
33                    log::error!("Failed to parse JSON: {}", err);
34                    return Vec::new();
35                }
36            }
37        }
38        Err(err) => {
39            log::error!("Error retrieving result: {}", err);
40            return Vec::new();
41        }
42    }
43    let mut gpu_info = Vec::new();
44    let na = "N/A".to_string();
45    for display in displays {
46        if let Some(model) = display.get("sppci_model") {
47            let mut info = HashMap::new();
48            info.insert(
49                "model".to_string(),
50                model.as_str()
51                    .unwrap_or(na.as_str())
52                    .to_string(),
53            );
54
55            // Handle cores
56            info.insert(
57                "cores".to_string(),
58                display.get("sppci_cores")
59                    .or(display.get("spdisplays_cores"))
60                    .and_then(|v| v.as_str())
61                    .unwrap_or(&na)
62                    .to_string(),
63            );
64
65            // Handle memory
66            info.insert(
67                "memory".to_string(),
68                display.get("sppci_vram")
69                    .or(display.get("spdisplays_vram"))
70                    .and_then(|v| v.as_str())
71                    .unwrap_or(&na)
72                    .to_string(),
73            );
74
75            // Handle vendor
76            info.insert(
77                "vendor".to_string(),
78                display.get("sppci_vendor")
79                    .and_then(|v| v.as_str())
80                    .unwrap_or(&na)
81                    .to_string(),
82            );
83            gpu_info.push(info);
84        }
85    }
86    gpu_info
87}
88
89/// Function to get GPU information for Linux machines.
90///
91/// # Arguments
92///
93/// * `lib_path` - The path to the library used to get GPU information.
94///
95/// # Returns
96///
97/// A `Vec` of `HashMap` containing GPU(s) information if successful, otherwise an empty `Vec`.
98fn get_gpu_info_linux(lib_path: &str) -> Vec<HashMap<String, String>> {
99    let result = squire::util::run_command(
100        lib_path,
101        &[],
102        true,
103    );
104    let output = match result {
105        Ok(output) => output,
106        Err(_) => return Vec::new(),
107    };
108    let mut gpu_info = Vec::new();
109    for line in output.lines() {
110        if line.contains("VGA") {
111            let gpu = line.split(':').last().unwrap().trim();
112            let mut info = HashMap::new();
113            info.insert("model".to_string(), gpu.to_string());
114            gpu_info.push(info);
115        }
116    }
117    gpu_info
118}
119
120/// Function to get GPU information for Windows machines.
121///
122/// # Arguments
123///
124/// * `lib_path` - The path to the library used to get GPU information.
125///
126/// # Returns
127///
128/// A `Vec` of `HashMap` containing GPU(s) information if successful, otherwise an empty `Vec`.
129fn get_gpu_info_windows(lib_path: &str) -> Vec<HashMap<String, String>> {
130    let result = squire::util::run_command(
131        lib_path,
132        &["path", "win32_videocontroller", "get", "Name,AdapterCompatibility", "/format:csv"],
133        true,
134    );
135    let output = match result {
136        Ok(output) => output.to_uppercase(),
137        Err(_) => {
138            return Vec::new();
139        }
140    };
141    let gpus_raw: Vec<&str> = output.lines().filter(|line| !line.trim().is_empty()).collect();
142    if gpus_raw.is_empty() {
143        log::info!("No GPUs found!");
144        return vec![];
145    }
146
147    let keys: Vec<String> = gpus_raw[0]
148        .trim()
149        .to_lowercase()
150        .replace("adaptercompatibility", "vendor")
151        .replace("name", "model")
152        .split(',')
153        .map(|key| key.to_string())
154        .collect();
155
156    let binding = gpus_raw[1..].join("");
157    let values: Vec<&str> = binding.trim().split(",").collect();
158    let mut gpu_info = Vec::new();
159    let key_len = keys.len();
160    for chunk in values.chunks(key_len) {
161        let mut map = HashMap::new();
162        for (key, value) in keys.iter().zip(chunk) {
163            map.insert(key.to_string(), value.to_string());
164        }
165        gpu_info.push(map);
166    }
167    gpu_info
168}
169
170/// OS-agnostic function to get GPU name.
171///
172/// # Returns
173///
174/// A `Vec` of `HashMap` containing GPU(s) information if successful, otherwise an empty `Vec`.
175pub fn get_gpu_info() -> Vec<HashMap<String, String>> {
176    let operating_system = std::env::consts::OS;
177    match operating_system {
178        "macos" => get_gpu_info_darwin("/usr/sbin/system_profiler"),
179        "linux" => get_gpu_info_linux("/usr/bin/lspci"),
180        "windows" => get_gpu_info_windows("C:\\Windows\\System32\\wbem\\wmic.exe"),
181        _ => {
182            log::error!("Unsupported operating system: {}", operating_system);
183            Vec::new()
184        }
185    }
186}