use anyhow::{anyhow, Result};
use spdx::identifiers::LICENSES;
use spdx::{imprecise_license_id, license_id, Expression, ParseMode};
pub fn try_find_by_id<I>(expr: I) -> Result<Option<String>>
where
I: AsRef<str>,
{
let expr = expr.as_ref();
if is_single_expr(expr) {
let license_id = partially_find_license(expr);
return Ok(license_id);
}
if let Ok(license) = Expression::parse_mode(expr, ParseMode::LAX) {
let license_id = Some(license.to_string());
return Ok(license_id);
}
let expr = Expression::canonicalize(expr)?;
Ok(expr)
}
fn partially_find_license(expr: &str) -> Option<String> {
license_id(expr)
.or_else(|| imprecise_license_id(expr).map(|(license_id, _)| license_id))
.map(|l| l.name.to_string())
}
fn is_single_expr(expr: &str) -> bool {
expr.split(' ').collect::<Vec<&str>>().len() == 1
}
pub fn list_spdx_license_names() -> Vec<String> {
LICENSES
.iter()
.map(|(_, fullname, _)| fullname.to_string())
.collect()
}
pub fn id_from_license_fullname(name: &str) -> Result<String> {
let item = LICENSES
.iter()
.find(|(_, fullname, _)| name == *fullname)
.map(|(id, fullname, _)| *id);
if item.is_none() {
return Err(anyhow!("no SPDX ID found for name: '{}'", name));
}
Ok(item.unwrap().to_string())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_try_find_by_id_exact() {
let expr = "BSD-3-Clause-No-Nuclear-License";
let license_id = try_find_by_id(expr);
println!("{:?}", license_id);
assert!(&license_id.is_ok());
}
#[test]
fn test_try_find_by_id_invalid() {
let expr = "BSE";
let license_id = try_find_by_id(expr);
assert!(&license_id.unwrap().is_none());
}
#[test]
fn test_try_find_by_id_combined() {
let expr = "mit or apache";
let license_id = try_find_by_id(expr);
assert!(&license_id.is_ok());
}
}