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
#![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};
pub trait License {
fn name(&self) -> &str;
fn id(&self) -> &str;
fn text(&self) -> &str;
fn permissions(&self) -> Permissions;
fn conditions(&self) -> Conditions;
fn limitations(&self) -> Limitations;
fn is_osi_approved(&self) -> bool;
fn is_fsf_free(&self) -> bool;
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! {
pub struct Permissions: u8 {
const COMMERCIAL_USE = 0b00000001;
const DISTRIBUTION = 0b00000010;
const MODIFICATION = 0b00000100;
const PATENT_RIGHTS = 0b00001000;
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! {
pub struct Conditions: u8 {
const DISCLOSE_SOURCES = 0b00000001;
const DOCUMENT_CHANGES = 0b00000010;
const LICENSE_AND_COPYRIGHT_NOTICE = 0b00000100;
const NETWORK_USE_IS_DISTRIBUTION = 0b00001000;
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! {
pub struct Limitations: u8 {
const NO_LIABILITY = 0b00000001;
const NO_TRADEMARK_RIGHTS = 0b00000010;
const NO_WARRANTY = 0b00000100;
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(())
}
}