use fst::Set;
use once_cell::sync::Lazy;
use packageurl::PackageUrl;
use std::env;
use std::str::FromStr;
static FST_DATA: &[u8] = include_bytes!(concat!(env!("OUT_DIR"), "/purls.fst"));
static VALIDATOR: Lazy<Set<&'static [u8]>> =
Lazy::new(|| Set::new(FST_DATA).expect("Failed to load FST from embedded bytes"));
fn strip_and_check_purl(packageurl: &str, fst_map: &Set<&[u8]>) -> Result<bool, ValidateError> {
let purl = PackageUrl::from_str(packageurl).map_err(ValidateError::InvalidPurl)?;
if purl.version().is_some() || !purl.qualifiers().is_empty() || purl.subpath().is_some() {
return Err(ValidateError::UnsupportedPurl(
"only base PURL is supported (no version, qualifiers, or subpath)",
));
}
let trimmed_packageurl = packageurl.trim_end_matches("/");
Ok(fst_map.contains(trimmed_packageurl))
}
pub fn validate(packageurl: &str) -> Result<bool, ValidateError> {
strip_and_check_purl(packageurl, &VALIDATOR)
}
#[derive(Debug)]
pub enum ValidateError {
InvalidPurl(packageurl::Error),
UnsupportedPurl(&'static str),
}
#[cfg(test)]
mod validate_tests;