use serde::{Deserialize, Serialize};
#[derive(Clone, Debug, Deserialize, Serialize)]
#[serde(deny_unknown_fields)]
pub struct LibrarySource {
pub url: String,
#[serde(default = "default_require_signature")]
pub require_signature: bool,
#[serde(default)]
pub identity_regexp: Option<String>,
#[serde(default)]
pub oidc_issuer: Option<String>,
#[serde(default = "default_refresh_interval")]
pub refresh_interval_secs: u64,
#[serde(default)]
pub manifest_sha256: Option<String>,
}
impl LibrarySource {
#[allow(dead_code)] pub fn new(url: impl Into<String>) -> Self {
Self {
url: url.into(),
require_signature: default_require_signature(),
identity_regexp: None,
oidc_issuer: None,
refresh_interval_secs: default_refresh_interval(),
manifest_sha256: None,
}
}
}
fn default_require_signature() -> bool {
true
}
fn default_refresh_interval() -> u64 {
86_400
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn parses_minimal_source() {
let toml_str = r#"url = "https://cdn.example.com/manifest.json""#;
let src: LibrarySource = toml::from_str(toml_str).unwrap();
assert_eq!(src.url, "https://cdn.example.com/manifest.json");
assert!(src.require_signature);
assert_eq!(src.refresh_interval_secs, 86_400);
}
#[test]
fn parses_full_source() {
let toml_str = r#"
url = "https://cdn.example.com/manifest.json"
require_signature = false
identity_regexp = "^https://github\\.com/myorg/.+$"
oidc_issuer = "https://token.actions.githubusercontent.com"
refresh_interval_secs = 3600
"#;
let src: LibrarySource = toml::from_str(toml_str).unwrap();
assert!(!src.require_signature);
assert_eq!(
src.identity_regexp.as_deref(),
Some(r"^https://github\.com/myorg/.+$")
);
assert_eq!(src.refresh_interval_secs, 3600);
}
#[test]
fn rejects_unknown_fields() {
let toml_str = r#"
url = "https://cdn.example.com/manifest.json"
nonsense_field = true
"#;
let err = toml::from_str::<LibrarySource>(toml_str).unwrap_err();
assert!(format!("{err}").contains("nonsense_field"));
}
}