Veröffentlichte Quellen
Quellen als ZIP herunterladen
CH-J Tools
Durchsuchen Sie Verzeichnisse und Dateien einer bestimmten Anwendungsausgabe.
CH-J / Server Manager
872 Dateien
core-20261030T220507Z-61e4558d889f
Hinzugefügt: · Erstellt:
1
//! Version parsing/comparison (port of `shared/version.js`): 2–4 numeric components,2
//! optional prerelease and build metadata.4
use crate::core::error::{CoreError, CoreResult};5
use once_cell::sync::Lazy;6
use regex::Regex;7
use std::cmp::Ordering;9
static VERSION: Lazy<Regex> = Lazy::new(|| {10
Regex::new(r"^v?(\d+)\.(\d+)(?:\.(\d+))?(?:\.(\d+))?(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$").unwrap()11
});13
#[derive(Debug, Clone, PartialEq)]14
pub struct Version {15
pub numbers: [u64; 4],16
pub prerelease: Vec<String>,17
}19
pub fn parse_version(input: &str) -> CoreResult<Version> {20
let raw = input.trim();21
let caps = VERSION.captures(raw).ok_or_else(|| CoreError::plain(format!("Invalid version: {}", if raw.is_empty() { "<empty>" } else { raw })))?;22
let n = |i: usize| caps.get(i).map(|m| m.as_str().parse::<u64>().unwrap_or(u64::MAX)).unwrap_or(0);23
Ok(Version {24
numbers: [n(1), n(2), n(3), n(4)],25
prerelease: caps.get(5).map(|m| m.as_str().split('.').map(str::to_string).collect()).unwrap_or_default(),26
})27
}29
fn compare_prerelease(left: &[String], right: &[String]) -> Ordering {30
match (left.is_empty(), right.is_empty()) {31
(true, true) => return Ordering::Equal,32
(true, false) => return Ordering::Greater,33
(false, true) => return Ordering::Less,34
_ => {}35
}36
for i in 0..left.len().max(right.len()) {37
let (Some(l), Some(r)) = (left.get(i), right.get(i)) else {38
return if left.get(i).is_none() { Ordering::Less } else { Ordering::Greater };39
};40
if l == r {41
continue;42
}43
let ln = l.chars().all(|c| c.is_ascii_digit());44
let rn = r.chars().all(|c| c.is_ascii_digit());45
return match (ln, rn) {46
(true, true) => l.parse::<u128>().unwrap_or(0).cmp(&r.parse::<u128>().unwrap_or(0)),47
(true, false) => Ordering::Less,48
(false, true) => Ordering::Greater,49
_ => l.cmp(r),50
};51
}52
Ordering::Equal53
}55
pub fn compare_versions(left: &str, right: &str) -> CoreResult<Ordering> {56
let (l, r) = (parse_version(left)?, parse_version(right)?);57
Ok(l.numbers.cmp(&r.numbers).then_with(|| compare_prerelease(&l.prerelease, &r.prerelease)))58
}60
pub fn cmp_or_equal(left: &str, right: &str) -> Ordering {61
compare_versions(left, right).unwrap_or(Ordering::Equal)62
}64
#[cfg(test)]65
mod tests {66
use super::*;68
#[test]69
fn ordering() {70
assert_eq!(compare_versions("0.1.1", "0.1.0").unwrap(), Ordering::Greater);71
assert_eq!(compare_versions("1.0.0-alpha", "1.0.0").unwrap(), Ordering::Less);72
assert_eq!(compare_versions("1.0.0-alpha.2", "1.0.0-alpha.10").unwrap(), Ordering::Less);73
assert_eq!(compare_versions("1.0", "1.0.0.0").unwrap(), Ordering::Equal);74
assert_eq!(compare_versions("v2.0.0+build", "2.0.0").unwrap(), Ordering::Equal);75
assert!(parse_version("1").is_err());76
}77
}SHA-256
21f4c48ca8ccc12cb37617185b5a3818d08529a95731df0e208be2482111f0c9CH-J Proprietary Software License 1.14 · Die Quellen werden unter der CH-J Proprietary Software License 1.14 bereitgestellt. Ihre Verfügbarkeit ändert die Lizenzbedingungen nicht und gewährt keine zusätzlichen Rechte.
SHA-256 des Archivs
77380d4805485ffa4027fbe7858b5836f197a4aa9d52358a43e2d12d018744df