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
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
//! A library that provides license information from [spdx.org](https://spdx.org) in addition to limitation, condition, and
//! permission information for each license. The library also provides the ability to identify a given license from the
//! license text.
//!
//! The library currently supports the following licenses:
//!
//! * [AGPL-3.0](http://www.gnu.org/licenses/agpl-3.0)
//! * [Apache-2.0](https://www.apache.org/licenses/LICENSE-2.0)
//! * [CC0-1.0](http://creativecommons.org/publicdomain/zero/1.0/)
//! * [GPL-3.0](http://www.gnu.org/licenses/gpl-3.0)
//! * [LGPL-3.0](http://www.gnu.org/licenses/lgpl-3.0)
//! * [MIT](https://opensource.org/licenses/MIT)
//! * [MPL-2.0](https://www.mozilla.org/en-US/MPL/2.0/)
//! * [Unlicense](http://unlicense.org/)
//!
//! However, you can also create your own license by implementing the License trait.
//! By default all the licenses are enabled, but individual licenses can be enabled through feature gating.

#![doc(html_root_url = "https://docs.rs/license/0.7.2")]
#![deny(
bad_style,
bare_trait_objects,
missing_debug_implementations,
missing_docs,
unused_import_braces,
unused_qualifications,
unsafe_code,
unstable_features
)]

extern crate aho_corasick;
#[macro_use]
extern crate bitflags;
#[macro_use]
extern crate lazy_static;
extern crate url;

#[macro_use]
mod macros;

#[cfg(feature = "agpl3")]
mod agpl3;
#[cfg(feature = "apache2")]
mod apache2;
#[cfg(feature = "cc01")]
mod cc01;
#[cfg(feature = "gpl3")]
mod gpl3;
mod kind;
#[cfg(feature = "lgpl3")]
mod lgpl3;
#[cfg(feature = "mit")]
mod mit;
#[cfg(feature = "mpl2")]
mod mpl2;
mod unknown;
#[cfg(feature = "unlicense")]
mod unlicense;

#[cfg(feature = "agpl3")]
pub use agpl3::Agpl3;
#[cfg(feature = "apache2")]
pub use apache2::Apache2;
#[cfg(feature = "cc01")]
pub use cc01::Cc01;
#[cfg(feature = "gpl3")]
pub use gpl3::Gpl3;
pub use kind::Kind;
#[cfg(feature = "lgpl3")]
pub use lgpl3::Lgpl3;
#[cfg(feature = "mit")]
pub use mit::Mit;
#[cfg(feature = "mpl2")]
pub use mpl2::Mpl2;
pub use unknown::Unknown;
#[cfg(feature = "unlicense")]
pub use unlicense::Unlicense;

use std::ffi::OsStr;
use std::fmt::{self, Display, Formatter};

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

    /// The identifier of the license.
    ///
    /// Corresponds to the *Identifier* column from [spdx.org/licenses](https://spdx.org/licenses/).
    fn id(&self) -> &str;

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

    /// The permissions of the license.
    fn permissions(&self) -> Permissions;

    /// The conditions of the license.
    fn conditions(&self) -> Conditions;

    /// The limitations of the license.
    fn limitations(&self) -> Limitations;

    /// 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 Free.
    ///
    /// Corresponds to the *FSF Free/Libre?* column from [spdx.org/licenses](https://spdx.org/licenses/).
    fn is_fsf_free(&self) -> bool;

    /// The url of the license.
    fn url(&self) -> &url::Url;
}

impl Display for dyn License {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        f.write_str(self.text())
    }
}

impl AsRef<str> for dyn License {
    #[inline]
    fn as_ref(&self) -> &str {
        self.text()
    }
}

impl AsRef<OsStr> for dyn License {
    #[inline]
    fn as_ref(&self) -> &OsStr {
        self.text().as_ref()
    }
}

impl AsRef<[u8]> for dyn License {
    #[inline]
    fn as_ref(&self) -> &[u8] {
        self.text().as_ref()
    }
}

bitflags! {
    /// The permissions of the license.
    pub struct Permissions: u8 {
        /// May be used for commercial purposes.
        const COMMERCIAL_USE = 0b00000001;
        /// May be distributed.
        const DISTRIBUTION = 0b00000010;
        /// May be modified.
        const MODIFICATION = 0b00000100;
        /// Provides an express grant of patent rights from contributors.
        const PATENT_RIGHTS = 0b00001000;
        /// May be used for private purposes.
        const PRIVATE_USE = 0b00010000;
    }
}

impl Display for Permissions {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        if self.is_empty() {
            return f.write_str("- No permissions.\n");
        }

        if self.intersects(Permissions::COMMERCIAL_USE) {
            f.write_str("- May be used for commercial purposes.\n")?;
        }
        if self.intersects(Permissions::DISTRIBUTION) {
            f.write_str("- May be distributed.\n")?;
        }
        if self.intersects(Permissions::MODIFICATION) {
            f.write_str("- May be modified.\n")?;
        }
        if self.intersects(Permissions::PATENT_RIGHTS) {
            f.write_str("- Provides an express grant of patent rights from contributors.\n")?;
        }
        if self.intersects(Permissions::PRIVATE_USE) {
            f.write_str("- May be used for private purposes.\n")?;
        }
        Ok(())
    }
}

bitflags! {
    /// The conditions of the license.
    pub struct Conditions: u8 {
        /// Source code must be made available when the software is distributed.
        const DISCLOSE_SOURCES = 0b00000001;
        /// Changes made to the code must be documented.
        const DOCUMENT_CHANGES = 0b00000010;
        /// The license and copyright notice must be included with the software.
        const LICENSE_AND_COPYRIGHT_NOTICE = 0b00000100;
        /// Users who interact with the software via network are
        /// given the right to receive a copy of the source code.
        const NETWORK_USE_IS_DISTRIBUTION = 0b00001000;
        /// Modifications must be released under the same license.
        const SAME_LICENSE = 0b00010000;
    }
}

impl Display for Conditions {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        if self.is_empty() {
            return f.write_str("- No conditions.\n");
        }

        if self.intersects(Conditions::DISCLOSE_SOURCES) {
            f.write_str("- Source code must be made available when the software is distributed.\n")?;
        }
        if self.intersects(Conditions::DOCUMENT_CHANGES) {
            f.write_str("- Changes made to the code must be documented.\n")?;
        }
        if self.intersects(Conditions::LICENSE_AND_COPYRIGHT_NOTICE) {
            f.write_str("- The license and copyright notice must be included with the software.\n")?;
        }
        if self.intersects(Conditions::NETWORK_USE_IS_DISTRIBUTION) {
            f.write_str("- Users who interact with the software via network are given the right to receive a copy of the source code.\n")?;
        }
        if self.intersects(Conditions::SAME_LICENSE) {
            f.write_str("- Modifications must be released under the same license.\n")?;
        }
        Ok(())
    }
}

bitflags! {
    /// The limitations of the license.
    pub struct Limitations: u8 {
        /// Includes a limitation of liability.
        const NO_LIABILITY = 0b00000001;
        /// Does not grant trademark rights.
        const NO_TRADEMARK_RIGHTS = 0b00000010;
        /// Does not provide any warranty.
        const NO_WARRANTY = 0b00000100;
        /// Does not provide any rights in the patents of contributors.
        const NO_PATENT_RIGHTS = 0b00001000;
    }
}

impl Display for Limitations {
    #[inline]
    fn fmt(&self, f: &mut Formatter) -> fmt::Result {
        if self.is_empty() {
            return f.write_str("- No limitations.\n");
        }

        if self.intersects(Limitations::NO_LIABILITY) {
            f.write_str("- Includes a limitation of liability.\n")?;
        }
        if self.intersects(Limitations::NO_TRADEMARK_RIGHTS) {
            f.write_str("- Does not grant trademark rights.\n")?;
        }
        if self.intersects(Limitations::NO_WARRANTY) {
            f.write_str("- Does not provide any warranty.\n")?;
        }
        if self.intersects(Limitations::NO_PATENT_RIGHTS) {
            f.write_str("- Does not provide any rights in the patents of contributors.\n")?;
        }
        Ok(())
    }
}