blob: 5dd27dc597a4e13673eb2018ba413422e2d9f1b7 [file] [log] [blame]
use crate::Error;
use serde::{Deserialize, Serialize, Serializer};
use std::fmt::{Display, Formatter};
use std::str::FromStr;
#[derive(Clone, Debug, Eq, PartialEq, Default, Deserialize)]
#[serde(from = "String")]
/// Type representing licenses used for advisory content
#[non_exhaustive]
pub enum License {
/// Creative Commons Zero v1.0 Universal
/// SPDX identifier: CC0-1.0
#[default]
CcZero10,
/// Creative Commons Attribution 4.0 International
/// SPDX identifier: CC-BY-4.0
///
/// Note: For GitHub Security Advisories database,
/// providing a link is [documented](https://docs.github.com/en/site-policy/github-terms/github-terms-for-additional-products-and-features#advisory-database)
/// as fulfilling the attribution obligation for the CC-BY 4.0 license used.
///
/// For advisories imported from a GitHub Security Advisory, we follow this by putting the
/// original URL in the `url` filed of the RustSec advisory, as it assures the link will be
/// visible to downstream users.
CcBy40,
/// Other SPDX requirement
Other(String),
}
impl From<String> for License {
fn from(s: String) -> Self {
match s.as_str() {
"CC0-1.0" => License::CcZero10,
"CC-BY-4.0" => License::CcBy40,
_ => License::Other(s),
}
}
}
impl Serialize for License {
fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
where
S: Serializer,
{
serializer.serialize_str(self.spdx())
}
}
impl Display for License {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
write!(f, "{}", self.spdx())
}
}
impl License {
/// Get license as an `&str` containing the SPDX identifier
pub fn spdx(&self) -> &str {
match self {
License::CcBy40 => "CC-BY-4.0",
License::CcZero10 => "CC0-1.0",
License::Other(ref l) => l,
}
}
}
impl FromStr for License {
type Err = Error;
// Parse standard SPDX identifiers
fn from_str(s: &str) -> Result<Self, Self::Err> {
Ok(match s {
"CC0-1.0" => License::CcZero10,
"CC-BY-4.0" => License::CcBy40,
l => License::Other(l.to_string()),
})
}
}
#[cfg(test)]
mod tests {
use crate::advisory::License;
#[test]
fn serialize_licenses() {
assert_eq!(
serde_json::to_string(&License::CcBy40).unwrap(),
"\"CC-BY-4.0\"".to_string()
);
assert_eq!(
serde_json::to_string(&License::Other("MPL-2.0".to_string())).unwrap(),
"\"MPL-2.0\"".to_string()
);
}
#[test]
fn deserialize_licenses() {
let l: License = serde_json::from_str("\"CC-BY-4.0\"").unwrap();
assert_eq!(l, License::CcBy40);
let l: License = serde_json::from_str("\"MPL-2.0\"").unwrap();
assert_eq!(l, License::Other("MPL-2.0".to_string()));
}
}