Skip to main content

provenant/models/
output.rs

1use super::{FileInfo, Package, TopLevelDependency};
2use serde::{Deserialize, Serialize};
3
4pub const OUTPUT_FORMAT_VERSION: &str = "4.0.0";
5
6#[derive(Serialize, Deserialize, Debug)]
7/// Top-level ScanCode-compatible JSON payload.
8pub 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    pub files: Vec<FileInfo>,
21    pub license_references: Vec<LicenseReference>,
22    pub license_rule_references: Vec<LicenseRuleReference>,
23}
24
25#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
26pub struct Summary {
27    #[serde(skip_serializing_if = "Option::is_none")]
28    pub declared_license_expression: Option<String>,
29    #[serde(skip_serializing_if = "Option::is_none")]
30    pub license_clarity_score: Option<LicenseClarityScore>,
31    #[serde(skip_serializing_if = "Option::is_none")]
32    pub declared_holder: Option<String>,
33    #[serde(skip_serializing_if = "Option::is_none")]
34    pub primary_language: Option<String>,
35    #[serde(default, skip_serializing_if = "Vec::is_empty")]
36    pub other_license_expressions: Vec<TallyEntry>,
37    #[serde(default, skip_serializing_if = "Vec::is_empty")]
38    pub other_holders: Vec<TallyEntry>,
39    #[serde(default, skip_serializing_if = "Vec::is_empty")]
40    pub other_languages: Vec<TallyEntry>,
41}
42
43#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
44pub struct LicenseClarityScore {
45    pub score: usize,
46    pub declared_license: bool,
47    pub identification_precision: bool,
48    pub has_license_text: bool,
49    pub declared_copyrights: bool,
50    pub conflicting_license_categories: bool,
51    pub ambiguous_compound_licensing: bool,
52}
53
54#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
55pub struct TallyEntry {
56    pub value: Option<String>,
57    pub count: usize,
58}
59
60#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq, Default)]
61pub struct Tallies {
62    #[serde(default, skip_serializing_if = "Vec::is_empty")]
63    pub detected_license_expression: Vec<TallyEntry>,
64    #[serde(default, skip_serializing_if = "Vec::is_empty")]
65    pub copyrights: Vec<TallyEntry>,
66    #[serde(default, skip_serializing_if = "Vec::is_empty")]
67    pub holders: Vec<TallyEntry>,
68    #[serde(default, skip_serializing_if = "Vec::is_empty")]
69    pub authors: Vec<TallyEntry>,
70    #[serde(default, skip_serializing_if = "Vec::is_empty")]
71    pub programming_language: Vec<TallyEntry>,
72}
73
74impl Tallies {
75    pub fn is_empty(&self) -> bool {
76        self.detected_license_expression.is_empty()
77            && self.copyrights.is_empty()
78            && self.holders.is_empty()
79            && self.authors.is_empty()
80            && self.programming_language.is_empty()
81    }
82}
83
84#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Eq)]
85pub struct FacetTallies {
86    pub facet: String,
87    pub tallies: Tallies,
88}
89
90#[derive(Serialize, Deserialize, Debug)]
91/// Scan execution metadata stored in `output.headers`.
92pub struct Header {
93    pub start_timestamp: String,
94    pub end_timestamp: String,
95    pub duration: f64,
96    pub extra_data: ExtraData,
97    pub errors: Vec<String>,
98    pub output_format_version: String,
99}
100
101#[derive(Serialize, Deserialize, Debug)]
102/// Additional counters and environment details for a scan run.
103pub struct ExtraData {
104    pub files_count: usize,
105    pub directories_count: usize,
106    pub excluded_count: usize,
107    pub system_environment: SystemEnvironment,
108}
109
110#[derive(Serialize, Deserialize, Debug)]
111/// Host environment information captured during scan execution.
112pub struct SystemEnvironment {
113    pub operating_system: Option<String>,
114    pub cpu_architecture: String,
115    pub platform: String,
116    pub rust_version: String,
117}
118
119#[derive(Serialize, Deserialize, Debug)]
120/// Reference entry for a detected license.
121pub struct LicenseReference {
122    pub name: String,
123    pub short_name: String,
124    pub spdx_license_key: String,
125    pub text: String,
126}
127
128#[derive(Serialize, Deserialize, Debug)]
129/// Reference metadata for a license detection rule.
130pub struct LicenseRuleReference {
131    pub identifier: String,
132    pub license_expression: String,
133    pub is_license_text: bool,
134    pub is_license_notice: bool,
135    pub is_license_reference: bool,
136    pub is_license_tag: bool,
137    pub is_license_clue: bool,
138    pub is_license_intro: bool,
139}