scancode_rust/utils/
spdx.rs

1use std::collections::HashSet;
2
3/// Combines multiple license expressions into a single SPDX expression.
4/// Deduplicates, sorts, and combines the expressions with " AND ".
5pub fn combine_license_expressions(expressions: impl IntoIterator<Item = String>) -> Option<String> {
6    let unique_expressions: HashSet<String> = expressions.into_iter().collect();
7    if unique_expressions.is_empty() {
8        return None;
9    }
10
11    let mut sorted_expressions: Vec<String> = unique_expressions.into_iter().collect();
12    sorted_expressions.sort(); // Sort for consistent output
13
14    // Join multiple expressions with AND, wrapping individual expressions in parentheses if needed
15    let combined = sorted_expressions
16        .iter()
17        .map(|expr| {
18            // If expression contains spaces and isn't already wrapped in parentheses,
19            // it might have operators, so wrap it
20            if expr.contains(' ') && !(expr.starts_with('(') && expr.ends_with(')')) {
21                format!("({})", expr)
22            } else {
23                expr.clone()
24            }
25        })
26        .collect::<Vec<_>>()
27        .join(" AND ");
28
29    Some(combined)
30}