diff --git a/src/config.rs b/src/config.rs index 349f2a0..7e4e949 100644 --- a/src/config.rs +++ b/src/config.rs @@ -1,4 +1,9 @@ -use std::fmt::{self, Display}; +use std::{ + fmt::{self, Display}, + str::FromStr, +}; + +use crate::error::VersionError; #[derive(Debug, Clone, PartialEq, Eq)] pub enum MinecraftType { @@ -36,3 +41,70 @@ impl Display for Snapshot { write!(f, "{}w{:02}{}", self.year, self.week, self.build) } } + +impl FromStr for Version { + type Err = VersionError; + + fn from_str(s: &str) -> Result { + let mut split = s.split('.'); + + let major_str = split.next().ok_or(VersionError::MissingMajor)?; + let minor_str = split.next().ok_or(VersionError::MissingMinor)?; + let patch_str = split.next().ok_or(VersionError::MissingPatch)?; + + if split.next().is_some() { + return Err(VersionError::ExtraComponents); + } + + let major = major_str + .parse::() + .map_err(|_| VersionError::IncorrectMajor(major_str.to_string()))?; + + let minor = minor_str + .parse::() + .map_err(|_| VersionError::IncorrectMinor(minor_str.to_string()))?; + + let patch = patch_str + .parse::() + .map_err(|_| VersionError::IncorrectPatch(patch_str.to_string()))?; + + Ok(Self { + major, + minor, + patch, + }) + } +} + +impl FromStr for Snapshot { + type Err = VersionError; + + fn from_str(s: &str) -> Result { + let (year_str, rest) = s + .split_once('w') + .ok_or(VersionError::InvalidSnapshotFormat)?; + + if rest.len() < 3 { + return Err(VersionError::InvalidSnapshotFormat); + } + + let week_str = &rest[..2]; + let build_str = &rest[2..]; + + let year = year_str + .parse::() + .map_err(|_| VersionError::IncorrectYear(year_str.to_string()))?; + + let week = week_str + .parse::() + .map_err(|_| VersionError::IncorrectWeek(week_str.to_string()))?; + + let build = if build_str.len() == 1 { + build_str.chars().next().unwrap() + } else { + return Err(VersionError::IncorrectBuild(build_str.to_string())); + }; + + Ok(Self { year, week, build }) + } +} diff --git a/src/error.rs b/src/error.rs index 38bcd7b..ba7e9e8 100644 --- a/src/error.rs +++ b/src/error.rs @@ -6,4 +6,40 @@ pub enum Error { Generic, } +#[derive(Debug, Clone, Error)] +pub enum VersionError { + #[error("Incorrect major version: {0}")] + IncorrectMajor(String), + + #[error("Incorrect minor version: {0}")] + IncorrectMinor(String), + + #[error("Incorrect patch version: {0}")] + IncorrectPatch(String), + + #[error("Incorrect major version: {0}")] + IncorrectYear(String), + + #[error("Incorrect minor version: {0}")] + IncorrectWeek(String), + + #[error("Incorrect patch version: {0}")] + IncorrectBuild(String), + + #[error("Missing major version")] + MissingMajor, + + #[error("Missing minor version")] + MissingMinor, + + #[error("Missing patch version")] + MissingPatch, + + #[error("Invalid snapshot format")] + InvalidSnapshotFormat, + + #[error("Too many components")] + ExtraComponents, +} + type Result = std::result::Result;