1use std::process::Command;
2
3use camino::Utf8Path;
4
5pub(crate) fn query_cdb_version(cdb: &Utf8Path) -> Option<[u16; 4]> {
6 let mut version = None;
7 if let Ok(output) = Command::new(cdb).arg("/version").output() {
8 if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
9 version = extract_cdb_version(&first_line);
10 }
11 }
12 version
13}
14
15pub(crate) fn extract_cdb_version(full_version_line: &str) -> Option<[u16; 4]> {
16 let version = full_version_line.rsplit(' ').next()?;
18 let mut components = version.split('.');
19 let major: u16 = components.next().unwrap().parse().unwrap();
20 let minor: u16 = components.next().unwrap().parse().unwrap();
21 let patch: u16 = components.next().unwrap_or("0").parse().unwrap();
22 let build: u16 = components.next().unwrap_or("0").parse().unwrap();
23 Some([major, minor, patch, build])
24}
25
26pub(crate) fn query_gdb_version(gdb: &Utf8Path) -> Option<u32> {
27 let mut version_line = None;
28 if let Ok(output) = Command::new(&gdb).arg("--version").output() {
29 if let Some(first_line) = String::from_utf8_lossy(&output.stdout).lines().next() {
30 version_line = Some(first_line.to_string());
31 }
32 }
33
34 let version = match version_line {
35 Some(line) => extract_gdb_version(&line),
36 None => return None,
37 };
38
39 version
40}
41
42pub(crate) fn extract_gdb_version(full_version_line: &str) -> Option<u32> {
43 let full_version_line = full_version_line.trim();
44
45 let unbracketed_part = full_version_line.split('[').next().unwrap();
57 let mut splits = unbracketed_part.trim_end().rsplit(' ');
58 let version_string = splits.next().unwrap();
59
60 let mut splits = version_string.split('.');
61 let major = splits.next().unwrap();
62 let minor = splits.next().unwrap();
63 let patch = splits.next();
64
65 let major: u32 = major.parse().unwrap();
66 let (minor, patch): (u32, u32) = match minor.find(not_a_digit) {
67 None => {
68 let minor = minor.parse().unwrap();
69 let patch: u32 = match patch {
70 Some(patch) => match patch.find(not_a_digit) {
71 None => patch.parse().unwrap(),
72 Some(idx) if idx > 3 => 0,
73 Some(idx) => patch[..idx].parse().unwrap(),
74 },
75 None => 0,
76 };
77 (minor, patch)
78 }
79 Some(idx) => {
81 let minor = minor[..idx].parse().unwrap();
82 (minor, 0)
83 }
84 };
85
86 Some(((major * 1000) + minor) * 1000 + patch)
87}
88
89pub(crate) fn extract_lldb_version(full_version_line: &str) -> Option<u32> {
91 let full_version_line = full_version_line.trim();
110
111 if let Some(apple_ver) =
112 full_version_line.strip_prefix("LLDB-").or_else(|| full_version_line.strip_prefix("lldb-"))
113 {
114 if let Some(idx) = apple_ver.find(not_a_digit) {
115 let version: u32 = apple_ver[..idx].parse().unwrap();
116 return Some(version);
117 }
118 } else if let Some(lldb_ver) = full_version_line.strip_prefix("lldb version ") {
119 if let Some(idx) = lldb_ver.find(not_a_digit) {
120 let version: u32 = lldb_ver[..idx].parse().ok()?;
121 return Some(version * 100);
122 }
123 }
124 None
125}
126
127fn not_a_digit(c: char) -> bool {
128 !c.is_ascii_digit()
129}