#[derive(Debug)]
pub(crate) struct WindowsVista {
vendor: String,
product: String,
release: Release,
editions: Editions,
}
impl WindowsVista {
pub(super) fn vendor(&self) -> &str {
self.vendor.as_str()
}
pub(super) fn product(&self) -> &str {
self.product.as_str()
}
pub(super) fn release(&self) -> String {
self.release.to_string()
}
pub(super) fn is_enterprise(&self) -> bool {
self.editions.contains(Edition::Enterprise)
|| self.editions.contains(Edition::Enterprise64bit)
|| self.editions.contains(Edition::EnterpriseX64)
}
pub(super) fn is_lts(&self) -> bool {
self.is_enterprise()
}
pub(super) fn to_string(&self) -> Vec<String> {
let out = self
.editions
.0
.iter()
.map(|edition| {
format!(
"{} {} {edition} {}",
self.vendor, self.product, self.release
)
})
.collect();
out
}
}
impl TryFrom<&str> for WindowsVista {
type Error = String;
fn try_from(value: &str) -> Result<Self, Self::Error> {
let parts: Vec<&str> = value.split('-').collect();
let parts: Vec<&str> = parts.iter().skip(1).map(|&s| s).collect();
if let Some(first) = parts.get(0) {
if *first != "6" {
Err(String::from("Not Windows Vista."))
} else {
if parts.len() < 2 {
Err(String::from("This is not a Windows Vista."))
} else {
if parts[0] == "6" {
let release = Release::try_from(parts[1])?;
Ok(WindowsVista {
vendor: "Microsoft".to_string(),
product: "Windows Vista".to_string(),
release,
editions: Editions::all(),
})
} else {
Err(String::from("This is not a Windows Vista."))
}
}
}
} else {
Err(String::from("This is not a Windows Vista."))
}
}
}
#[derive(Debug)]
enum Release {
#[allow(dead_code)]
GA,
SP1,
SP2,
}
impl TryFrom<&str> for Release {
type Error = String;
fn try_from(value: &str) -> Result<Self, Self::Error> {
match value.to_uppercase().as_str() {
"SP1" => Ok(Release::SP1),
"SP2" => Ok(Release::SP2),
_ => Err(String::from("This is not a Windows Vista Release.")),
}
}
}
impl std::fmt::Display for Release {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let out = match self {
Release::GA => "",
Release::SP1 => "SP1",
Release::SP2 => "SP2",
};
write!(f, "{}", out.to_string())
}
}
#[derive(Debug)]
struct Editions(Vec<Edition>);
impl Editions {
fn all() -> Self {
Editions(vec![
Edition::Business,
Edition::BusinessN,
Edition::BusinessN64bit,
Edition::Enterprise,
Edition::Enterprise64bit,
Edition::EnterpriseX64,
Edition::HomeBasic,
Edition::HomeBasic64bit,
Edition::HomeBasicN,
Edition::HomeBasicN64bit,
Edition::HomePremium,
Edition::HomePremium64bit,
Edition::Starter,
Edition::Ultimate,
Edition::Ultimate64bit,
])
}
#[allow(dead_code)]
fn contains(&self, edition: Edition) -> bool {
self.0.contains(&edition)
}
#[allow(dead_code)]
fn len(&self) -> usize {
self.0.len()
}
}
#[derive(PartialEq, Debug)]
enum Edition {
Business,
BusinessN,
BusinessN64bit,
Enterprise,
Enterprise64bit,
EnterpriseX64,
HomeBasic,
HomeBasic64bit,
HomeBasicN,
HomeBasicN64bit,
HomePremium,
HomePremium64bit,
Starter,
Ultimate,
Ultimate64bit,
}
impl std::fmt::Display for Edition {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let out = match self {
Edition::Business => "Business",
Edition::BusinessN => "Business N",
Edition::BusinessN64bit => "Business N 64-bit",
Edition::Enterprise => "Enterprise",
Edition::Enterprise64bit => "Enterprise 64-bit",
Edition::EnterpriseX64 => "Enterprise X64",
Edition::HomeBasic => "Home Basic",
Edition::HomeBasic64bit => "Home Basic 64-bit",
Edition::HomeBasicN => "Home Basic N",
Edition::HomeBasicN64bit => "Home Basic N 64-bit",
Edition::HomePremium => "Home Premium",
Edition::HomePremium64bit => "Home Premium 64-bit",
Edition::Starter => "Starter",
Edition::Ultimate => "Ultimate",
Edition::Ultimate64bit => "Ultimate 64-bit",
};
write!(f, "{}", out.to_string())
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_from_string() {
let label = WindowsVista::try_from("windows-6-sp2").unwrap();
assert_eq!(label.vendor, "Microsoft".to_string());
assert_eq!(label.product, "Windows Vista".to_string());
assert_eq!(label.release.to_string(), "SP2".to_string());
assert_eq!(label.editions.len(), Editions::all().len());
}
}