pub fn key(user: &str, url: &str) -> String {
format!("{user}:{url}")
}
pub fn version(v: &str) -> Result<versions::SemVer, String> {
versions::SemVer::new(v)
.map(trim_version)
.ok_or_else(|| format!("invalid version string '{}'", v))
}
pub fn trim_version(sv: versions::SemVer) -> versions::SemVer {
versions::SemVer {
major: sv.major,
minor: sv.minor,
patch: sv.patch,
pre_rel: None,
meta: None,
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_key_basic() {
assert_eq!(key("user1", "example.com"), "user1:example.com");
}
#[test]
fn test_key_empty_user() {
assert_eq!(key("", "example.com"), ":example.com");
}
#[test]
fn test_key_empty_url() {
assert_eq!(key("user1", ""), "user1:");
}
#[test]
fn test_key_both_empty() {
assert_eq!(key("", ""), ":");
}
#[test]
fn test_key_special_characters() {
assert_eq!(
key("user@email.com", "https://example.com/path"),
"user@email.com:https://example.com/path"
);
}
#[test]
fn test_key_unicode() {
assert_eq!(key("用户", "例え.com"), "用户:例え.com");
}
#[test]
fn test_version_basic() {
let v = version("1.2.3").unwrap();
assert_eq!(v.major, 1);
assert_eq!(v.minor, 2);
assert_eq!(v.patch, 3);
assert!(v.pre_rel.is_none());
assert!(v.meta.is_none());
}
#[test]
fn test_version_with_prerelease() {
let v = version("2.0.0-beta.1").unwrap();
assert_eq!(v.major, 2);
assert_eq!(v.minor, 0);
assert_eq!(v.patch, 0);
assert!(v.pre_rel.is_none(), "Pre-release should be stripped");
assert!(v.meta.is_none());
}
#[test]
fn test_version_with_metadata() {
let v = version("1.0.0+20130313144700").unwrap();
assert_eq!(v.major, 1);
assert_eq!(v.minor, 0);
assert_eq!(v.patch, 0);
assert!(v.pre_rel.is_none());
assert!(v.meta.is_none(), "Metadata should be stripped");
}
#[test]
fn test_version_zero() {
let v = version("0.0.0").unwrap();
assert_eq!(v.major, 0);
assert_eq!(v.minor, 0);
assert_eq!(v.patch, 0);
}
#[test]
fn test_version_large_numbers() {
let v = version("999.888.777").unwrap();
assert_eq!(v.major, 999);
assert_eq!(v.minor, 888);
assert_eq!(v.patch, 777);
}
#[test]
fn test_trim_version_basic() {
let original = versions::SemVer::new("1.2.3").unwrap();
let trimmed = trim_version(original.clone());
assert_eq!(trimmed.major, 1);
assert_eq!(trimmed.minor, 2);
assert_eq!(trimmed.patch, 3);
assert!(trimmed.pre_rel.is_none());
assert!(trimmed.meta.is_none());
}
#[test]
fn test_trim_version_removes_prerelease() {
let original = versions::SemVer::new("1.0.0-alpha").unwrap();
let trimmed = trim_version(original);
assert_eq!(trimmed.major, 1);
assert_eq!(trimmed.minor, 0);
assert_eq!(trimmed.patch, 0);
assert!(
trimmed.pre_rel.is_none(),
"Pre-release should be removed by trim"
);
}
#[test]
fn test_trim_version_removes_metadata() {
let original = versions::SemVer::new("2.1.0+build.123").unwrap();
let trimmed = trim_version(original);
assert_eq!(trimmed.major, 2);
assert_eq!(trimmed.minor, 1);
assert_eq!(trimmed.patch, 0);
assert!(trimmed.meta.is_none(), "Metadata should be removed by trim");
}
#[test]
fn test_trim_version_removes_both() {
let original = versions::SemVer::new("3.2.1-rc.1+build").unwrap();
let trimmed = trim_version(original);
assert_eq!(trimmed.major, 3);
assert_eq!(trimmed.minor, 2);
assert_eq!(trimmed.patch, 1);
assert!(trimmed.pre_rel.is_none());
assert!(trimmed.meta.is_none());
}
#[test]
fn version_comparisons() {
assert!(version("1.1.0") > version("1.0.0"));
assert_eq!(version("1.1.0"), version("1.1.0-RC1"));
assert_eq!(version("1.1.0"), version("1.1.0-dev"));
assert!(version("1.1.0-dev") > version("1.0.9"));
}
#[test]
fn test_version_comparisons_extended() {
assert!(version("2.0.0") > version("1.9.9"));
assert!(version("1.0.1") > version("1.0.0"));
assert!(version("1.1.0") > version("1.0.9"));
assert_eq!(version("1.0.0"), version("1.0.0"));
assert_eq!(version("1.0.0-alpha"), version("1.0.0-beta"));
assert_eq!(version("1.0.0+build1"), version("1.0.0+build2"));
}
#[test]
fn test_version_with_dev_suffix() {
let v1 = version("0.9.0-dev");
let v2 = version("0.9.0");
assert_eq!(v1, v2, "Dev suffix should be ignored in comparison");
}
#[test]
fn test_version_with_rc_suffix() {
let v1 = version("1.0.0-RC1");
let v2 = version("1.0.0-RC2");
let v3 = version("1.0.0");
assert_eq!(v1, v2, "RC versions should compare equal when trimmed");
assert_eq!(v1, v3, "RC version should equal release version");
}
}