1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88
use std::error::Error; use std::fmt; mod spdx; use self::LicenseExpr::*; #[derive(Debug, Clone, Copy)] pub enum LicenseExpr<'a> { License(&'a str), Exception(&'a str), And, Or, With, } impl<'a> fmt::Display for LicenseExpr<'a> { fn fmt(&self, format: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { With => format.write_str("WITH"), And => format.write_str("AND"), Or => format.write_str("OR"), License(info) | Exception(info) => format.write_str(info), } } } #[derive(Debug, Clone, Copy)] pub enum ParseError<'a> { UnknownLicenseId(&'a str), InvalidStructure(LicenseExpr<'a>), } impl<'a> fmt::Display for ParseError<'a> { fn fmt(&self, format: &mut fmt::Formatter) -> Result<(), fmt::Error> { match *self { ParseError::UnknownLicenseId(info) => { format.write_fmt(format_args!("{}: {}", self.description(), info)) } ParseError::InvalidStructure(info) => { format.write_fmt(format_args!("{}: {}", self.description(), info)) } } } } impl<'a> Error for ParseError<'a> { fn description(&self) -> &str { match *self { ParseError::UnknownLicenseId(_) => "unknown license or other term", ParseError::InvalidStructure(_) => "invalid license expression", } } } pub fn validate_license_expr(license_expr: &str) -> Result<(), ParseError> { license_expr .split_whitespace() .map(|word| match word { "AND" => Ok(And), "OR" => Ok(Or), "WITH" => Ok(With), _ if spdx::LICENSES .binary_search(&word.trim_end_matches('+')) .is_ok() => { Ok(License(word)) } _ if spdx::EXCEPTIONS.binary_search(&word).is_ok() => Ok(Exception(word)), _ => Err(ParseError::UnknownLicenseId(word)), }) .fold(Ok(Or), |prev, word| match (prev, word) { (err @ Err(_), _) | (_, err @ Err(_)) => err, (Ok(License(_)), Ok(With)) | (Ok(License(_)), Ok(And)) | (Ok(License(_)), Ok(Or)) | (Ok(Exception(_)), Ok(And)) | (Ok(Exception(_)), Ok(Or)) | (Ok(And), Ok(License(_))) | (Ok(Or), Ok(License(_))) | (Ok(With), Ok(Exception(_))) => word, _ => Err(ParseError::InvalidStructure(word.unwrap())), }) .and(Ok(())) } pub fn license_version() -> &'static str { spdx::VERSION }