1use super::{FileInfo, Match, Package, TopLevelDependency};
2use serde::{Deserialize, Serialize};
3
4pub const OUTPUT_FORMAT_VERSION: &str = "4.0.0";
5
6#[derive(Serialize, Deserialize, Debug)]
7pub struct Output {
9 #[serde(skip_serializing_if = "Option::is_none")]
10 pub summary: Option<Summary>,
11 #[serde(skip_serializing_if = "Option::is_none")]
12 pub tallies: Option<Tallies>,
13 #[serde(skip_serializing_if = "Option::is_none")]
14 pub tallies_of_key_files: Option<Tallies>,
15 #[serde(skip_serializing_if = "Option::is_none")]
16 pub tallies_by_facet: Option<Vec<FacetTallies>>,
17 pub headers: Vec<Header>,
18 pub packages: Vec<Package>,
19 pub dependencies: Vec<TopLevelDependency>,
20 #[serde(default, skip_serializing_if = "Vec::is_empty")]
21 pub license_detections: Vec<TopLevelLicenseDetection>,
22 pub files: Vec<FileInfo>,
23 pub license_references: Vec<LicenseReference>,
24 pub license_rule_references: Vec<LicenseRuleReference>,
25}
26
27#[derive(Serialize, Deserialize, Debug, Clone, PartialEq)]
28pub struct TopLevelLicenseDetection {
29 pub identifier: String,
30 pub license_expression: String,
31 pub license_expression_spdx: String,
32 pub detection_count: usize,
33 #[serde(skip_serializing_if = "Vec::is_empty", default)]
34 pub detection_log: Vec<String>,
35 pub reference_matches: Vec<Match>,
36}
37
38#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
39pub struct Summary {
40 #[serde(skip_serializing_if = "Option::is_none")]
41 pub declared_license_expression: Option<String>,
42 #[serde(skip_serializing_if = "Option::is_none")]
43 pub license_clarity_score: Option<LicenseClarityScore>,
44 #[serde(skip_serializing_if = "Option::is_none")]
45 pub declared_holder: Option<String>,
46 #[serde(skip_serializing_if = "Option::is_none")]
47 pub primary_language: Option<String>,
48 #[serde(default, skip_serializing_if = "Vec::is_empty")]
49 pub other_license_expressions: Vec<TallyEntry>,
50 #[serde(default, skip_serializing_if = "Vec::is_empty")]
51 pub other_holders: Vec<TallyEntry>,
52 #[serde(default, skip_serializing_if = "Vec::is_empty")]
53 pub other_languages: Vec<TallyEntry>,
54}
55
56#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
57pub struct LicenseClarityScore {
58 pub score: usize,
59 pub declared_license: bool,
60 pub identification_precision: bool,
61 pub has_license_text: bool,
62 pub declared_copyrights: bool,
63 pub conflicting_license_categories: bool,
64 pub ambiguous_compound_licensing: bool,
65}
66
67#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
68pub struct TallyEntry {
69 pub value: Option<String>,
70 pub count: usize,
71}
72
73#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
74pub struct Tallies {
75 #[serde(default, skip_serializing_if = "Vec::is_empty")]
76 pub detected_license_expression: Vec<TallyEntry>,
77 #[serde(default, skip_serializing_if = "Vec::is_empty")]
78 pub copyrights: Vec<TallyEntry>,
79 #[serde(default, skip_serializing_if = "Vec::is_empty")]
80 pub holders: Vec<TallyEntry>,
81 #[serde(default, skip_serializing_if = "Vec::is_empty")]
82 pub authors: Vec<TallyEntry>,
83 #[serde(default, skip_serializing_if = "Vec::is_empty")]
84 pub programming_language: Vec<TallyEntry>,
85}
86
87impl Tallies {
88 pub fn is_empty(&self) -> bool {
89 self.detected_license_expression.is_empty()
90 && self.copyrights.is_empty()
91 && self.holders.is_empty()
92 && self.authors.is_empty()
93 && self.programming_language.is_empty()
94 }
95}
96
97#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
98pub struct FacetTallies {
99 pub facet: String,
100 pub tallies: Tallies,
101}
102
103#[derive(Serialize, Deserialize, Debug)]
104pub struct Header {
106 pub start_timestamp: String,
107 pub end_timestamp: String,
108 pub duration: f64,
109 pub extra_data: ExtraData,
110 pub errors: Vec<String>,
111 pub output_format_version: String,
112}
113
114#[derive(Serialize, Deserialize, Debug)]
115pub struct ExtraData {
117 pub files_count: usize,
118 pub directories_count: usize,
119 pub excluded_count: usize,
120 pub system_environment: SystemEnvironment,
121}
122
123#[derive(Serialize, Deserialize, Debug)]
124pub struct SystemEnvironment {
126 pub operating_system: Option<String>,
127 pub cpu_architecture: String,
128 pub platform: String,
129 pub rust_version: String,
130}
131
132#[derive(Serialize, Deserialize, Debug)]
133pub struct LicenseReference {
135 #[serde(default, skip_serializing_if = "Option::is_none")]
136 pub key: Option<String>,
137 #[serde(default, skip_serializing_if = "Option::is_none")]
138 pub language: Option<String>,
139 pub name: String,
140 pub short_name: String,
141 #[serde(default, skip_serializing_if = "Option::is_none")]
142 pub owner: Option<String>,
143 #[serde(default, skip_serializing_if = "Option::is_none")]
144 pub homepage_url: Option<String>,
145 pub spdx_license_key: String,
146 #[serde(default, skip_serializing_if = "Vec::is_empty")]
147 pub other_spdx_license_keys: Vec<String>,
148 #[serde(default, skip_serializing_if = "Option::is_none")]
149 pub osi_license_key: Option<String>,
150 #[serde(default, skip_serializing_if = "Vec::is_empty")]
151 pub text_urls: Vec<String>,
152 #[serde(default, skip_serializing_if = "Option::is_none")]
153 pub osi_url: Option<String>,
154 #[serde(default, skip_serializing_if = "Option::is_none")]
155 pub faq_url: Option<String>,
156 #[serde(default, skip_serializing_if = "Vec::is_empty")]
157 pub other_urls: Vec<String>,
158 #[serde(default, skip_serializing_if = "Option::is_none")]
159 pub category: Option<String>,
160 #[serde(default)]
161 pub is_exception: bool,
162 #[serde(default)]
163 pub is_unknown: bool,
164 #[serde(default)]
165 pub is_generic: bool,
166 #[serde(default, skip_serializing_if = "Option::is_none")]
167 pub notes: Option<String>,
168 #[serde(default, skip_serializing_if = "Option::is_none")]
169 pub minimum_coverage: Option<u8>,
170 #[serde(default, skip_serializing_if = "Option::is_none")]
171 pub standard_notice: Option<String>,
172 #[serde(default, skip_serializing_if = "Vec::is_empty")]
173 pub ignorable_copyrights: Vec<String>,
174 #[serde(default, skip_serializing_if = "Vec::is_empty")]
175 pub ignorable_holders: Vec<String>,
176 #[serde(default, skip_serializing_if = "Vec::is_empty")]
177 pub ignorable_authors: Vec<String>,
178 #[serde(default, skip_serializing_if = "Vec::is_empty")]
179 pub ignorable_urls: Vec<String>,
180 #[serde(default, skip_serializing_if = "Vec::is_empty")]
181 pub ignorable_emails: Vec<String>,
182 #[serde(default, skip_serializing_if = "Option::is_none")]
183 pub scancode_url: Option<String>,
184 #[serde(default, skip_serializing_if = "Option::is_none")]
185 pub licensedb_url: Option<String>,
186 #[serde(default, skip_serializing_if = "Option::is_none")]
187 pub spdx_url: Option<String>,
188 pub text: String,
189}
190
191#[derive(Serialize, Deserialize, Debug)]
192pub struct LicenseRuleReference {
194 pub identifier: String,
195 pub license_expression: String,
196 pub is_license_text: bool,
197 pub is_license_notice: bool,
198 pub is_license_reference: bool,
199 pub is_license_tag: bool,
200 pub is_license_clue: bool,
201 pub is_license_intro: bool,
202 #[serde(default, skip_serializing_if = "Option::is_none")]
203 pub language: Option<String>,
204 #[serde(default, skip_serializing_if = "Option::is_none")]
205 pub rule_url: Option<String>,
206 #[serde(default)]
207 pub is_required_phrase: bool,
208 #[serde(default)]
209 pub skip_for_required_phrase_generation: bool,
210 #[serde(default)]
211 pub is_continuous: bool,
212 #[serde(default)]
213 pub is_synthetic: bool,
214 #[serde(default)]
215 pub is_from_license: bool,
216 #[serde(default)]
217 pub length: usize,
218 #[serde(default, skip_serializing_if = "Option::is_none")]
219 pub relevance: Option<u8>,
220 #[serde(default, skip_serializing_if = "Option::is_none")]
221 pub minimum_coverage: Option<u8>,
222 #[serde(default, skip_serializing_if = "Vec::is_empty")]
223 pub referenced_filenames: Vec<String>,
224 #[serde(default, skip_serializing_if = "Option::is_none")]
225 pub notes: Option<String>,
226 #[serde(default, skip_serializing_if = "Vec::is_empty")]
227 pub ignorable_copyrights: Vec<String>,
228 #[serde(default, skip_serializing_if = "Vec::is_empty")]
229 pub ignorable_holders: Vec<String>,
230 #[serde(default, skip_serializing_if = "Vec::is_empty")]
231 pub ignorable_authors: Vec<String>,
232 #[serde(default, skip_serializing_if = "Vec::is_empty")]
233 pub ignorable_urls: Vec<String>,
234 #[serde(default, skip_serializing_if = "Vec::is_empty")]
235 pub ignorable_emails: Vec<String>,
236 #[serde(default, skip_serializing_if = "Option::is_none")]
237 pub text: Option<String>,
238}