Accept a version string for the plugin manifest api field

Fixes #1040

Co-Authored-By: Claude Haiku 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
This commit is contained in:
NetterSilver
2026-10-23 00:13:46 +02:00
co-authored by Claude Haiku 5.5
parent 80f916326f
commit ffe61d1880
2 changed files with 29 additions and 1 deletions
+20 -1
View File
@@ -44,7 +44,7 @@ pub struct Manifest {
pub main: String,
/// The plugin API version the plugin was written for (1 when not given; panels and settings
/// need 2, widgets 3).
#[serde(default = "api_version")]
#[serde(default = "api_version", deserialize_with = "api_from_number_or_string")]
pub api: u32,
#[serde(default)]
pub permissions: Permissions,
@@ -61,6 +61,25 @@ fn api_version() -> u32 {
1
}
/// `api` as a whole number or a version string (`"1.0.0"`, whose major part is the API version).
fn api_from_number_or_string<'de, D: serde::Deserializer<'de>>(d: D) -> Result<u32, D::Error> {
#[derive(Deserialize)]
#[serde(untagged)]
enum Api {
Number(u32),
Text(String),
}
match Api::deserialize(d)? {
Api::Number(n) => Ok(n),
Api::Text(s) => s
.trim()
.split('.')
.next()
.and_then(|major| major.parse().ok())
.ok_or_else(|| serde::de::Error::custom(format!("invalid api version `{s}`"))),
}
}
/// What a plugin may do.
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct Permissions {
+9
View File
@@ -462,3 +462,12 @@ fn bad_manifests_are_refused() {
assert!(Manifest::parse(junk).is_err(), "accepted {}", junk.chars().take(40).collect::<String>());
}
}
#[test]
fn api_may_be_a_version_string() {
assert_eq!(manifest(json!({"api": "1.0.0"})).unwrap().api, 1);
assert_eq!(manifest(json!({"api": "2"})).unwrap().api, 2);
assert_eq!(manifest(json!({"api": 2})).unwrap().api, 2);
assert!(manifest(json!({"api": "4.0.0"})).is_err());
assert!(manifest(json!({"api": "x"})).is_err());
}