1use std::hash::Hash;
2
3use serde::{Deserialize, Serialize};
4use spdx::Expression;
5
6#[derive(Debug, Clone, Serialize, Deserialize)]
20#[serde(untagged, try_from = "ExprInternal", into = "ExprInternal")]
21pub enum License {
22 Single(Box<Expression>),
24
25 AnyOf(Vec<Expression>),
27}
28
29impl License {
30 pub fn to_expression(&self) -> Expression {
32 match self {
33 Self::Single(exp) => *exp.clone(),
34 Self::AnyOf(exps) => Expression::parse(
35 &exps
36 .iter()
37 .map(|exp| format!("({exp})"))
38 .collect::<Vec<_>>()
39 .join(" OR "),
40 )
41 .expect("if the original expressions parsed, this one will too"),
42 }
43 }
44}
45
46impl Hash for License {
47 fn hash<H: std::hash::Hasher>(&self, state: &mut H) {
48 self.to_expression().to_string().hash(state)
49 }
50}
51
52impl PartialEq for License {
53 fn eq(&self, other: &Self) -> bool {
54 self.to_expression().eq(&other.to_expression())
55 }
56}
57
58impl Eq for License {}
59
60#[derive(Debug, Clone, Serialize, Deserialize)]
61#[serde(untagged)]
62enum ExprInternal {
63 Single(String),
64 AnyOf(Vec<String>),
65}
66
67impl TryFrom<ExprInternal> for License {
68 type Error = spdx::ParseError;
69
70 fn try_from(value: ExprInternal) -> Result<Self, Self::Error> {
71 match value {
72 ExprInternal::Single(expr) => {
73 let expr = Expression::parse(&expr)?;
74 Ok(Self::Single(Box::new(expr)))
75 }
76 ExprInternal::AnyOf(exprs) => {
77 let mut exps = Vec::with_capacity(exprs.len());
78 for exp in exprs {
79 exps.push(Expression::parse(&exp)?);
80 }
81 Ok(Self::AnyOf(exps))
82 }
83 }
84 }
85}
86
87impl From<License> for ExprInternal {
88 fn from(license: License) -> Self {
89 match license {
90 License::Single(exp) => Self::Single(exp.to_string()),
91 License::AnyOf(exps) => Self::AnyOf(exps.into_iter().map(|e| e.to_string()).collect()),
92 }
93 }
94}