Repository: typst/typst
File: crates/typst-syntax/src/package.rs (Rust)

Code before:
    /// element in the bound is actually greater than that of the version.
    ///
    /// ```
    /// # use typst_syntax::package::{PackageVersion, SemVerBound};
    /// # use std::str::FromStr;
    /// let v1_1_1 = PackageVersion::from_str("1.1.1").unwrap();
    ///
    /// assert!(v1_1_1.matches_gt(&SemVerBound::from_str("0").unwrap()));
    /// assert!(!v1_1_1.matches_gt(&SemVerBound::from_str("1").unwrap()));
    /// assert!(!v1_1_1.matches_gt(&SemVerBound::from_str("2").unwrap()));
    ///
    /// assert!(v1_1_1.matches_gt(&SemVerBound::from_str("1.0").unwrap()));
    /// assert!(!v1_1_1.matches_gt(&SemVerBound::from_str("1.1").unwrap()));
    /// assert!(!v1_1_1.matches_gt(&SemVerBound::from_str("1.2").unwrap()));
    ///
    /// assert!(v1_1_1.matches_gt(&SemVerBound::from_str("1.1.0").unwrap()));
    /// assert!(!v1_1_1.matches_gt(&SemVerBound::from_str("1.1.1").unwrap()));
    /// assert!(!v1_1_1.matches_gt(&SemVerBound::from_str("1.1.2").unwrap()));
    /// ```
    pub fn matches_gt(&self, bound: &SemVerBound) -> bool {
        if self.major != bound.major {
            return self.major > bound.major;
        }
        let Some(minor) = bound.minor else {
            return false;
        };
        if self.minor != minor {
            return self.minor > minor;
        }
        let Some(patch) = bound.patch else {
            return false;
        };
        if self.patch != patch {
            return self.patch > patch;
        }
        false
    }

    /// Performs a `<` match with the given version bound. The match only succeeds if some version
    /// element in the bound is actually less than that of the version.
    ///
    /// ```
    /// # use typst_syntax::package::{PackageVersion, SemVerBound};
    /// # use std::str::FromStr;
    /// let v1_1_1 = PackageVersion::from_str("1.1.1").unwrap();
    ///
    /// assert!(!v1_1_1.matches_lt(&SemVerBound::from_str("0").unwrap()));
    /// assert!(!v1_1_1.matches_lt(&SemVerBound::from_str("1").unwrap()));
    /// assert!(v1_1_1.matches_lt(&SemVerBound::from_str("2").unwrap()));
    ///
    /// assert!(!v1_1_1.matches_lt(&SemVerBound::from_str("1.0").unwrap()));

Review comment (suggestion):
```suggestion
        let Some(minor) = bound.minor else { return false };
```
if we remove the semicolon, it formats a little nicer in my opinion

Code after:
        }
        false
    }

    /// Performs a `>=` match with the given versions. The match succeeds when
    /// either a `==` or `>` match does.
    pub fn matches_ge(&self, bound: &VersionBound) -> bool {
        self.matches_eq(bound) || self.matches_gt(bound)
    }

    /// Performs a `<=` match with the given versions. The match succeeds when
    /// either a `==` or `<` match does.
    pub fn matches_le(&self, bound: &VersionBound) -> bool {
        self.matches_eq(bound) || self.matches_lt(bound)
    }
}

impl FromStr for PackageVersion {
    type Err = EcoString;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        let mut parts = s.split('.');
        let mut next = |kind| {
            let part = parts
                .next()
                .filter(|s| !s.is_empty())
                .ok_or_else(|| eco_format!("version number is missing {kind} version"))?;
            part.parse::<u32>()
                .map_err(|_| eco_format!("`{part}` is not a valid {kind} version"))
        };

        let major = next("major")?;
        let minor = next("minor")?;
        let patch = next("patch")?;
        if let Some(rest) = parts.next() {
            Err(eco_format!("version number has unexpected fourth component: `{rest}`"))?;
        }

        Ok(Self { major, minor, patch })
    }
}

impl Debug for PackageVersion {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Display::fmt(self, f)
    }
}

impl Display for PackageVersion {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        write!(f, "{}.{}.{}", self.major, self.minor, self.patch)