[go: up one dir, main page]

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
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
//! **Embedded license information from [SPDX](https://spdx.org).**
//!
//! Use the licenses directly.
//!
//! ```
//! use license::License;
//! use license::licenses::Bsd3Clause;
//!
//! let bsd3 = Bsd3Clause;
//! assert!(bsd3.is_osi_approved());
//! assert_eq!(bsd3.name(), r#"BSD 3-Clause "New" or "Revised" License"#);
//! ```
//!
//! Get the license by parsing the license id.
//!
//! ```
//! use license::License;
//!
//! let apache2: &dyn License = "Apache-2.0".parse().unwrap();
//! assert_eq!(apache2.name(), "Apache License 2.0");
//! ```
//!
//! License exceptions are also supported.
//!
//! ```
//! use license::Exception;
//!
//! let gcc: &dyn Exception = "GCC-exception-3.1".parse().unwrap();
//! assert_eq!(gcc.name(), "GCC Runtime Library exception 3.1");
//! ```
//!
//! [Serde](https://crates.io/crates/serde) is supported with the `serde` feature.

#![no_std]
#![doc(html_root_url = "https://docs.rs/license")]
#![deny(missing_docs, unsafe_code)]

#[cfg(feature = "serde")]
mod serde;

use core::fmt::{self, Debug, Display, Formatter};
use core::str::FromStr;

/// All supported licenses.
pub mod licenses {
    include!(concat!(env!("OUT_DIR"), "/licenses.rs"));
}

/// All supported exceptions.
pub mod exceptions {
    include!(concat!(env!("OUT_DIR"), "/exceptions.rs"));
}

/// Base functionality for all licenses.
pub trait License {
    /// The identifier of the license.
    ///
    /// Corresponds to the *Identifier* column from [spdx.org/licenses](https://spdx.org/licenses/).
    fn id(&self) -> &'static str;

    /// The name of the license.
    ///
    /// Corresponds to the *Full name* column from [spdx.org/licenses](https://spdx.org/licenses/).
    fn name(&self) -> &'static str;

    /// The license text.
    fn text(&self) -> &'static str;

    /// The standard license header.
    fn header(&self) -> Option<&'static str>;

    /// Says if the license is OSI approved.
    ///
    /// Corresponds to the *OSI Approved?* column from [spdx.org/licenses](https://spdx.org/licenses/).
    fn is_osi_approved(&self) -> bool;

    /// Says if the license is FSF Libre.
    ///
    /// Corresponds to the *FSF Free/Libre?* column from [spdx.org/licenses](https://spdx.org/licenses/).
    fn is_fsf_libre(&self) -> bool;

    /// Says if the license is deprecated.
    fn is_deprecated(&self) -> bool;

    /// The license comments.
    fn comments(&self) -> Option<&'static str>;

    /// Relevant sources.
    fn see_also(&self) -> &'static [&'static str];
}

/// Base functionality for all license exceptions.
pub trait Exception {
    /// The identifier of the exceptions.
    fn id(&self) -> &'static str;

    /// The name of the exception.
    fn name(&self) -> &'static str;

    /// The exception text.
    fn text(&self) -> &'static str;

    /// Says if the exception is deprecated.
    fn is_deprecated(&self) -> bool;

    /// The exception comments.
    fn comments(&self) -> Option<&'static str>;

    /// Relevant sources.
    fn see_also(&self) -> &'static [&'static str];
}

impl Display for dyn License {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Display::fmt(self.name(), f)
    }
}

impl Display for dyn Exception {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Display::fmt(self.name(), f)
    }
}

impl Debug for dyn License {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Debug::fmt(self.id(), f)
    }
}

impl Debug for dyn Exception {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Debug::fmt(self.id(), f)
    }
}

impl FromStr for &dyn License {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        licenses::parse_id(s).ok_or(ParseError(()))
    }
}

impl FromStr for &dyn Exception {
    type Err = ParseError;

    fn from_str(s: &str) -> Result<Self, Self::Err> {
        exceptions::parse_id(s).ok_or(ParseError(()))
    }
}

/// Error returned when parsing license and exception ids.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct ParseError(());

impl Display for ParseError {
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        Display::fmt("SPDX id not found", f)
    }
}