pub struct Expression { /* private fields */ }
Expand description
An SPDX license expression that is both syntactically and semantically valid, and can be evaluated
use spdx::Expression;
let this_is_fine = Expression::parse("MIT OR Apache-2.0").unwrap();
assert!(this_is_fine.evaluate(|req| {
if let spdx::LicenseItem::Spdx { id, .. } = req.license {
// Both MIT and Apache-2.0 are OSI approved, so this expression
// evaluates to true
return id.is_osi_approved();
}
false
}));
assert!(!this_is_fine.evaluate(|req| {
if let spdx::LicenseItem::Spdx { id, .. } = req.license {
// This is saying we don't accept any licenses that are OSI approved
// so the expression will evaluate to false as both sides of the OR
// are now rejected
return !id.is_osi_approved();
}
false
}));
// `NOPE` is not a valid SPDX license identifier, so this expression
// will fail to parse
let _this_is_not = Expression::parse("MIT OR NOPE").unwrap_err();
Implementations§
Source§impl Expression
impl Expression
Sourcepub fn minimized_requirements<'lic>(
&self,
accepted: impl IntoIterator<Item = &'lic Licensee>,
) -> Result<Vec<LicenseReq>, MinimizeError>
pub fn minimized_requirements<'lic>( &self, accepted: impl IntoIterator<Item = &'lic Licensee>, ) -> Result<Vec<LicenseReq>, MinimizeError>
Given a set of Licensee
s, attempts to find the minimum number that
satisfy this Expression
.
The list of licensees should be given in priority order, eg, if you wish
to accept the Apache-2.0
license if it is available, and the MIT
if
not, putting Apache-2.0
before MIT
will cause the ubiquitous
Apache-2.0 OR MIT
expression to minimize to just Apache-2.0
as only
1 of the licenses is required, and Apache-2.0
has priority.
§Errors
This method will fail if more than 64 unique licensees are satisfied by this expression, but such a case is unlikely in a real world scenario. The list of licensees must also actually satisfy this expression, otherwise it can’t be minimized.
§Example
let expr = spdx::Expression::parse("Apache-2.0 OR MIT").unwrap();
let apache_licensee = spdx::Licensee::parse("Apache-2.0").unwrap();
assert_eq!(
expr.minimized_requirements([&apache_licensee, &spdx::Licensee::parse("MIT").unwrap()]).unwrap(),
vec![apache_licensee.into_req()],
);
Source§impl Expression
impl Expression
Sourcepub fn parse(original: &str) -> Result<Self, ParseError>
pub fn parse(original: &str) -> Result<Self, ParseError>
Given a license expression, attempts to parse and validate it as a valid
SPDX expression. Uses ParseMode::Strict
.
The validation can fail for many reasons:
- The expression contains invalid characters
- An unknown/invalid license or exception identifier was found. Only SPDX short identifiers are allowed
- The expression contained unbalanced parentheses
- A license or exception immediately follows another license or exception, without a valid AND, OR, or WITH operator separating them
- An AND, OR, or WITH doesn’t have a license or
)
preceding it
spdx::Expression::parse("MIT OR Apache-2.0 WITH LLVM-exception").unwrap();
Sourcepub fn canonicalize(original: &str) -> Result<Option<String>, ParseError>
pub fn canonicalize(original: &str) -> Result<Option<String>, ParseError>
Canonicalizes the input expression into a form that can be parsed with
ParseMode::STRICT
§Transforms
- ‘/’ is replaced with ’ OR ’
- Lower-cased operators (‘or’, ‘and’, ‘with’) are upper-cased
- ‘+’ is tranformed to
-or-later
for GNU licenses - Invalid/imprecise license identifiers (eg.
apache2
) are replaced with their valid identifiers
If the provided expression is not modified then None
is returned
Note that this only does fixup of otherwise valid expressions, passing
the resulting string to Expression::parse
can still result in
additional parse errors, eg. unbalanced parentheses
assert_eq!(spdx::Expression::canonicalize("apache with LLVM-exception/gpl-3.0+").unwrap().unwrap(), "Apache-2.0 WITH LLVM-exception OR GPL-3.0-or-later");
Sourcepub fn parse_mode(original: &str, mode: ParseMode) -> Result<Self, ParseError>
pub fn parse_mode(original: &str, mode: ParseMode) -> Result<Self, ParseError>
Parses an expression with the specified ParseMode
. With
ParseMode::Lax
it permits some non-SPDX syntax, such as imprecise
license names and “/” used instead of “OR” in exprssions.
spdx::Expression::parse_mode(
"mit/Apache-2.0 WITH LLVM-exception",
spdx::ParseMode::LAX
).unwrap();
Source§impl Expression
impl Expression
Sourcepub fn requirements(&self) -> impl Iterator<Item = &ExpressionReq>
pub fn requirements(&self) -> impl Iterator<Item = &ExpressionReq>
Returns each of the license requirements in the license expression, but not the operators that join them together
let expr = spdx::Expression::parse("MIT AND BSD-2-Clause").unwrap();
assert_eq!(
&expr.requirements().map(|er| er.req.license.id()).collect::<Vec<_>>(), &[
spdx::license_id("MIT"),
spdx::license_id("BSD-2-Clause")
]
);
Sourcepub fn iter(&self) -> impl Iterator<Item = &ExprNode>
pub fn iter(&self) -> impl Iterator<Item = &ExprNode>
Returns both the license requirements and the operators that join them together. Note that the expression is returned in post fix order.
use spdx::expression::{ExprNode, Operator};
let expr = spdx::Expression::parse("Apache-2.0 OR MIT").unwrap();
let mut ei = expr.iter();
assert!(ei.next().is_some()); // Apache
assert!(ei.next().is_some()); // MIT
assert_eq!(*ei.next().unwrap(), ExprNode::Op(Operator::Or));
Sourcepub fn evaluate<AF: FnMut(&LicenseReq) -> bool>(&self, allow_func: AF) -> bool
pub fn evaluate<AF: FnMut(&LicenseReq) -> bool>(&self, allow_func: AF) -> bool
Evaluates the expression, using the provided function to determine if the licensee meets the requirements for each license term. If enough requirements are satisfied the evaluation will return true.
use spdx::Expression;
let this_is_fine = Expression::parse("MIT OR Apache-2.0").unwrap();
assert!(this_is_fine.evaluate(|req| {
// If we find MIT, then we're happy!
req.license.id() == spdx::license_id("MIT")
}));
Sourcepub fn evaluate_with_failures<AF: FnMut(&LicenseReq) -> bool>(
&self,
allow_func: AF,
) -> Result<(), Vec<&ExpressionReq>>
pub fn evaluate_with_failures<AF: FnMut(&LicenseReq) -> bool>( &self, allow_func: AF, ) -> Result<(), Vec<&ExpressionReq>>
Just as with evaluate, the license expression is evaluated to see if enough license requirements in the expression are met for the evaluation to succeed, except this method also keeps track of each failed requirement and returns them, allowing for more detailed error reporting about precisely what terms in the expression caused the overall failure
Trait Implementations§
Source§impl AsRef<str> for Expression
impl AsRef<str> for Expression
Source§impl Clone for Expression
impl Clone for Expression
Source§fn clone(&self) -> Expression
fn clone(&self) -> Expression
1.0.0 · Source§fn clone_from(&mut self, source: &Self)
fn clone_from(&mut self, source: &Self)
source
. Read more