use std::collections::HashMap;
use crate::license_detection::expression::{
LicenseExpression, expression_to_string, parse_expression,
};
use crate::license_detection::models::License;
#[derive(Debug, Clone)]
pub struct SpdxMapping {
scancode_to_spdx: HashMap<String, String>,
}
impl SpdxMapping {
pub fn build_from_licenses(licenses: &[License]) -> Self {
let mut scancode_to_spdx = HashMap::new();
for license in licenses {
let scancode_key = &license.key;
if let Some(spdx_key) = &license.spdx_license_key {
scancode_to_spdx.insert(scancode_key.clone(), spdx_key.clone());
} else {
let licenseref_key = format!("LicenseRef-scancode-{}", scancode_key);
scancode_to_spdx.insert(scancode_key.clone(), licenseref_key.clone());
}
}
Self { scancode_to_spdx }
}
pub fn scancode_to_spdx(&self, scancode_key: &str) -> Option<String> {
self.scancode_to_spdx.get(scancode_key).cloned()
}
pub fn expression_scancode_to_spdx(&self, scancode_expr: &str) -> Result<String, String> {
let parsed = parse_expression(scancode_expr).map_err(|e| format!("Parse error: {}", e))?;
let converted = self.convert_expression_to_spdx(&parsed);
Ok(expression_to_string(&converted))
}
fn convert_expression_to_spdx(&self, expr: &LicenseExpression) -> LicenseExpression {
match expr {
LicenseExpression::License(key) => {
if let Some(spdx_key) = self.scancode_to_spdx(key) {
if spdx_key.starts_with("LicenseRef-") {
LicenseExpression::LicenseRef(spdx_key)
} else {
LicenseExpression::License(spdx_key)
}
} else {
LicenseExpression::LicenseRef(format!("LicenseRef-scancode-{}", key))
}
}
LicenseExpression::LicenseRef(key) => {
if let Some(spdx_key) = self.scancode_to_spdx(key) {
LicenseExpression::LicenseRef(spdx_key)
} else {
LicenseExpression::LicenseRef(key.clone())
}
}
LicenseExpression::And { left, right } => LicenseExpression::And {
left: Box::new(self.convert_expression_to_spdx(left)),
right: Box::new(self.convert_expression_to_spdx(right)),
},
LicenseExpression::Or { left, right } => LicenseExpression::Or {
left: Box::new(self.convert_expression_to_spdx(left)),
right: Box::new(self.convert_expression_to_spdx(right)),
},
LicenseExpression::With { left, right } => LicenseExpression::With {
left: Box::new(self.convert_expression_to_spdx(left)),
right: Box::new(self.convert_expression_to_spdx(right)),
},
}
}
}
pub fn build_spdx_mapping(licenses: &[License]) -> SpdxMapping {
SpdxMapping::build_from_licenses(licenses)
}
#[cfg(test)]
mod test;