const TOOL_TYPES: &[(u16, &str)] = &[
(0x0001, "[IMP]"),
(0x0002, "[EXP]"),
(0x0004, "[LNK]"),
(0x0003, "[ASM]"),
(0x0007, "[ASM]"),
(0x000F, "[ASM]"),
(0x0045, "[ASM]"),
(0x00AA, "[ASM]"),
(0x00FF, "[ASM]"),
(0x0100, "[ASM]"),
(0x0101, "[ASM]"),
(0x0006, "[C]"),
(0x000A, "[C]"),
(0x0015, "[C]"),
(0x001C, "[C]"),
(0x006D, "[C]"),
(0x0083, "[C]"),
(0x00DA, "[C]"),
(0x00DB, "[C]"),
(0x00DC, "[C]"),
(0x0104, "[C]"),
(0x0105, "[C]"),
(0x0106, "[C]"),
(0x0002, "[C++]"),
(0x000B, "[C++]"),
(0x0016, "[C++]"),
(0x001D, "[C++]"),
(0x006E, "[C++]"),
(0x0084, "[C++]"),
(0x00DD, "[C++]"),
(0x00DE, "[C++]"),
(0x00DF, "[C++]"),
(0x0107, "[C++]"),
(0x0108, "[C++]"),
(0x0109, "[C++]"),
(0x0005, "[RES]"),
(0x0009, "[RES]"),
(0x005E, "[RES]"),
(0x009D, "[RES]"),
(0x0093, "[RES]"),
(0x0008, "[CVTRES]"),
(0x000C, "[CVTRES]"),
(0x000D, "[CVTRES]"),
(0x0060, "[CVTRES]"),
(0x005D, "[CVTRES]"),
(0x000E, "[LNK]"),
(0x005F, "[LNK]"),
(0x0078, "[LNK]"),
(0x00E0, "[LNK]"),
(0x00FC, "[LNK]"),
(0x00FD, "[LNK]"),
(0x0102, "[LNK]"),
(0x010A, "[LNK]"),
(0x010B, "[LNK]"),
(0x010C, "[LNK]"),
(0x0014, "[LTCG]"),
(0x00C7, "[LTCG]"),
(0x0013, "[POGO]"),
(0x00C6, "[POGO]"),
];
const VS_VERSIONS: &[(u16, u16, &str)] = &[
(8047, 8799, "VS 6.0"),
(8800, 9799, "VS 6.0 SP5-6"),
(9466, 9500, "VS 2002 (7.0)"),
(3077, 7000, "VS 2003 (7.1)"),
(50320, 50399, "VS 2005 (8.0)"),
(50400, 50799, "VS 2005 SP1"),
(21022, 21099, "VS 2008 (9.0)"),
(21100, 21299, "VS 2008 SP1"),
(30729, 30749, "VS 2008 SP1"),
(30319, 30399, "VS 2010 (10.0)"),
(30400, 30499, "VS 2010 SP1"),
(40219, 40299, "VS 2010 SP1"),
(50727, 50799, "VS 2012 (11.0)"),
(51025, 51199, "VS 2012 Update 1-4"),
(51106, 51199, "VS 2012 Update 4"),
(21005, 21020, "VS 2013 (12.0)"),
(23026, 23099, "VS 2015 (14.0)"),
(23506, 23599, "VS 2015 Update 1"),
(23918, 23999, "VS 2015 Update 2"),
(24210, 24299, "VS 2015 Update 3"),
(24215, 24299, "VS 2015 Update 3.1"),
(25017, 25099, "VS 2017 15.0"),
(25506, 25599, "VS 2017 15.3"),
(25831, 25899, "VS 2017 15.5"),
(25835, 25899, "VS 2017 15.5"),
(26128, 26199, "VS 2017 15.6"),
(26428, 26499, "VS 2017 15.7"),
(26726, 26799, "VS 2017 15.8"),
(26905, 26999, "VS 2017 15.9"),
(27508, 27599, "VS 2019 16.0"),
(27702, 27799, "VS 2019 16.1"),
(27905, 27999, "VS 2019 16.2"),
(28105, 28199, "VS 2019 16.3"),
(28314, 28399, "VS 2019 16.4"),
(28610, 28699, "VS 2019 16.5"),
(28805, 28899, "VS 2019 16.6"),
(29110, 29199, "VS 2019 16.7"),
(29333, 29399, "VS 2019 16.8"),
(29336, 29399, "VS 2019 16.8"),
(29910, 29999, "VS 2019 16.9"),
(29913, 29999, "VS 2019 16.9"),
(30036, 30099, "VS 2019 16.10"),
(30133, 30199, "VS 2019 16.11"),
(30401, 30499, "VS 2022 17.0"),
(30818, 30899, "VS 2022 17.1"),
(31104, 31199, "VS 2022 17.2"),
(31329, 31399, "VS 2022 17.3"),
(31332, 31399, "VS 2022 17.3"),
(31629, 31699, "VS 2022 17.4"),
(31937, 31999, "VS 2022 17.5"),
(31938, 31999, "VS 2022 17.5"),
(32215, 32299, "VS 2022 17.6"),
(32532, 32599, "VS 2022 17.7"),
(32824, 32899, "VS 2022 17.8"),
(33135, 33199, "VS 2022 17.9"),
(33433, 33499, "VS 2022 17.10"),
(33801, 33899, "VS 2022 17.11"),
(34108, 34199, "VS 2022 17.12"),
];
fn lookup_tool_type(prod_id: u16) -> &'static str {
for &(id, name) in TOOL_TYPES {
if id == prod_id {
return name;
}
}
"[???]"
}
fn lookup_vs_version(build_id: u16) -> Option<&'static str> {
for &(min, max, ver) in VS_VERSIONS {
if build_id >= min && build_id <= max {
return Some(ver);
}
}
None
}
pub fn lookup_rich_entry(prod_id: u16, build_id: u16) -> String {
let tool = lookup_tool_type(prod_id);
match lookup_vs_version(build_id) {
Some(ver) => format!("{} {} (build {})", tool, ver, build_id),
None => {
if tool == "[???]" {
format!("[???] Unknown (prod={:#06x}, build={})", prod_id, build_id)
} else {
format!("{} Unknown version (build {})", tool, build_id)
}
}
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn known_tool_and_version() {
let desc = lookup_rich_entry(0x0107, 29110);
assert!(desc.starts_with("[C++]"), "should be C++: {}", desc);
assert!(desc.contains("VS 2019"), "should contain VS 2019: {}", desc);
assert!(desc.contains("29110"), "should contain build id: {}", desc);
}
#[test]
fn known_tool_unknown_version() {
let desc = lookup_rich_entry(0x000E, 1);
assert!(desc.starts_with("[LNK]"), "should be LNK: {}", desc);
assert!(desc.contains("Unknown version"), "should say unknown version: {}", desc);
}
#[test]
fn unknown_tool_and_version() {
let desc = lookup_rich_entry(0xFFFF, 1);
assert!(desc.starts_with("[???]"), "should be ???: {}", desc);
assert!(desc.contains("Unknown"), "should say unknown: {}", desc);
}
#[test]
fn resource_compiler() {
let desc = lookup_rich_entry(0x0093, 50727);
assert!(desc.starts_with("[RES]"), "should be RES: {}", desc);
}
}