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
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
//! Package licensing.
//!
//! **Note:** this module re-exports all of [`linfo`](https://docs.rs/linfo).

use std::{
    fmt,
    borrow::Cow,
};

mod serde;

// BUG(docs): `Expr` and `SpdxLicense` don't get rendered despite the glob. They
// would, however, still be available within this module with just the glob.
#[doc(inline)]
pub use linfo::{*, Expr, SpdxLicense};

/// Any license, known or otherwise.
#[derive(Clone, Debug, PartialEq, Eq, Hash)]
pub enum AnyLicense<'a> {
    /// A license known to Ocean.
    ///
    /// This means information such as OSI approval and "libre"-ness can be
    /// checked.
    Known(License),
    /// A license unknown to Ocean. This is generally treated as an opaque ID.
    Unknown(Cow<'a, str>),
}

impl From<License> for AnyLicense<'_> {
    #[inline]
    fn from(known: License) -> Self {
        Self::Known(known)
    }
}

impl From<SpdxLicense> for AnyLicense<'_> {
    #[inline]
    fn from(spdx: SpdxLicense) -> Self {
        Self::Known(spdx.into())
    }
}

impl<'a> From<&'a str> for AnyLicense<'a> {
    #[inline]
    fn from(s: &'a str) -> Self {
        if let Ok(l) = License::parse(s) {
            Self::Known(l)
        } else {
            Self::Unknown(Cow::Borrowed(s))
        }
    }
}

impl From<String> for AnyLicense<'_> {
    #[inline]
    fn from(s: String) -> Self {
        Cow::<'_, str>::Owned(s).into()
    }
}

impl<'a> From<Cow<'a, str>> for AnyLicense<'a> {
    #[inline]
    fn from(s: Cow<'a, str>) -> Self {
        if let Ok(l) = License::parse(s.as_ref()) {
            Self::Known(l)
        } else {
            Self::Unknown(s)
        }
    }
}

impl fmt::Display for AnyLicense<'_> {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        match self {
            Self::Known(known) => known.fmt(f),
            Self::Unknown(unknown) => unknown.fmt(f),
        }
    }
}

impl<'a> AnyLicense<'a> {
    /// Creates an instance from `s` where any external reference in `s` is not
    /// kept.
    #[inline]
    pub fn owned<S>(s: S) -> Self
        where S: Into<String> + AsRef<str>
    {
        if let Ok(l) = License::parse(s.as_ref()) {
            Self::Known(l)
        } else {
            Self::Unknown(Cow::Owned(s.into()))
        }
    }

    /// Returns the license's identifier by reference.
    #[inline]
    pub fn id(&self) -> &str {
        match self {
            Self::Known(l) => l.id(),
            Self::Unknown(id) => id,
        }
    }

    /// Returns whether the license is known to Ocean.
    #[inline]
    pub fn is_known(&self) -> bool {
        match self {
            Self::Known(_) => true,
            Self::Unknown(_) => false,
        }
    }
}