diff options
| author | nsfisis <nsfisis@gmail.com> | 2026-05-16 23:36:37 +0900 |
|---|---|---|
| committer | nsfisis <nsfisis@gmail.com> | 2026-05-16 23:36:37 +0900 |
| commit | beecbec6becfaaabcffd5bd9c596c055e64778c1 (patch) | |
| tree | 17774fb0c7ed2b45b72a11b53040862d1c3094af /crates/shirabe-semver | |
| parent | c1b57fb510961e02134df4883327155199d73087 (diff) | |
| download | php-shirabe-beecbec6becfaaabcffd5bd9c596c055e64778c1.tar.gz php-shirabe-beecbec6becfaaabcffd5bd9c596c055e64778c1.tar.zst php-shirabe-beecbec6becfaaabcffd5bd9c596c055e64778c1.zip | |
feat(port): port Semver.php
Diffstat (limited to 'crates/shirabe-semver')
| -rw-r--r-- | crates/shirabe-semver/src/semver.rs | 74 |
1 files changed, 74 insertions, 0 deletions
diff --git a/crates/shirabe-semver/src/semver.rs b/crates/shirabe-semver/src/semver.rs index 2d26366..8fecf27 100644 --- a/crates/shirabe-semver/src/semver.rs +++ b/crates/shirabe-semver/src/semver.rs @@ -1 +1,75 @@ //! ref: composer/vendor/composer/semver/src/Semver.php + +use std::sync::OnceLock; + +use crate::comparator::Comparator; +use crate::constraint::constraint::Constraint; +use crate::version_parser::VersionParser; + +pub struct Semver; + +impl Semver { + pub const SORT_ASC: i64 = 1; + pub const SORT_DESC: i64 = -1; + + fn version_parser() -> &'static VersionParser { + static VERSION_PARSER: OnceLock<VersionParser> = OnceLock::new(); + VERSION_PARSER.get_or_init(VersionParser::new) + } + + pub fn satisfies(version: String, constraints: String) -> anyhow::Result<bool> { + let version_parser = Self::version_parser(); + let provider = Constraint::new("==".to_string(), version_parser.normalize(version)?); + let parsed_constraints = version_parser.parse_constraints(constraints)?; + Ok(parsed_constraints.matches(&provider)) + } + + pub fn satisfied_by(versions: Vec<String>, constraints: String) -> anyhow::Result<Vec<String>> { + let mut result = Vec::new(); + for version in versions.iter() { + if Self::satisfies(version.clone(), constraints.clone())? { + result.push(version.clone()); + } + } + Ok(result) + } + + pub fn sort(versions: Vec<String>) -> anyhow::Result<Vec<String>> { + Self::usort(versions, Self::SORT_ASC) + } + + pub fn rsort(versions: Vec<String>) -> anyhow::Result<Vec<String>> { + Self::usort(versions, Self::SORT_DESC) + } + + fn usort(versions: Vec<String>, direction: i64) -> anyhow::Result<Vec<String>> { + let version_parser = Self::version_parser(); + + let mut normalized: Vec<(String, usize)> = versions + .iter() + .enumerate() + .map(|(key, version)| -> anyhow::Result<(String, usize)> { + let normalized_version = version_parser.normalize(version.clone())?; + let normalized_version = + version_parser.normalize_default_branch(normalized_version); + Ok((normalized_version, key)) + }) + .collect::<anyhow::Result<Vec<_>>>()?; + + normalized.sort_by(|left, right| { + if left.0 == right.0 { + return std::cmp::Ordering::Equal; + } + let is_less = Comparator::less_than(left.0.clone(), right.0.clone()); + let cmp_value = if is_less { -direction } else { direction }; + cmp_value.cmp(&0) + }); + + let sorted: Vec<String> = normalized + .into_iter() + .map(|(_, key)| versions[key].clone()) + .collect(); + + Ok(sorted) + } +} |
