Skip to main content

provenant/output_schema/
package.rs

1use serde::{Deserialize, Serialize};
2use std::collections::HashMap;
3
4use super::license_detection::OutputLicenseDetection;
5use super::party::OutputParty;
6use super::serde_helpers::serialize_optional_map_as_object;
7
8#[derive(Serialize, Deserialize, Debug, Clone)]
9pub struct OutputPackage {
10    #[serde(rename = "type")]
11    pub package_type: Option<crate::models::PackageType>,
12    pub namespace: Option<String>,
13    pub name: Option<String>,
14    pub version: Option<String>,
15    #[serde(default, serialize_with = "serialize_optional_map_as_object")]
16    pub qualifiers: Option<HashMap<String, String>>,
17    pub subpath: Option<String>,
18    pub primary_language: Option<String>,
19    pub description: Option<String>,
20    pub release_date: Option<String>,
21    #[serde(default)]
22    pub parties: Vec<OutputParty>,
23    #[serde(default)]
24    pub keywords: Vec<String>,
25    pub homepage_url: Option<String>,
26    pub download_url: Option<String>,
27    pub size: Option<u64>,
28    #[serde(skip_serializing_if = "Option::is_none")]
29    pub sha1: Option<String>,
30    #[serde(skip_serializing_if = "Option::is_none")]
31    pub md5: Option<String>,
32    #[serde(skip_serializing_if = "Option::is_none")]
33    pub sha256: Option<String>,
34    #[serde(skip_serializing_if = "Option::is_none")]
35    pub sha512: Option<String>,
36    pub bug_tracking_url: Option<String>,
37    pub code_view_url: Option<String>,
38    pub vcs_url: Option<String>,
39    pub copyright: Option<String>,
40    pub holder: Option<String>,
41    pub declared_license_expression: Option<String>,
42    pub declared_license_expression_spdx: Option<String>,
43    #[serde(default)]
44    pub license_detections: Vec<OutputLicenseDetection>,
45    pub other_license_expression: Option<String>,
46    pub other_license_expression_spdx: Option<String>,
47    #[serde(default)]
48    pub other_license_detections: Vec<OutputLicenseDetection>,
49    pub extracted_license_statement: Option<String>,
50    pub notice_text: Option<String>,
51    #[serde(default)]
52    pub source_packages: Vec<String>,
53    #[serde(default)]
54    pub is_private: bool,
55    #[serde(default)]
56    pub is_virtual: bool,
57    #[serde(default, serialize_with = "serialize_optional_map_as_object")]
58    pub extra_data: Option<HashMap<String, serde_json::Value>>,
59    pub repository_homepage_url: Option<String>,
60    pub repository_download_url: Option<String>,
61    pub api_data_url: Option<String>,
62    pub purl: Option<String>,
63    pub package_uid: String,
64    pub datafile_paths: Vec<String>,
65    pub datasource_ids: Vec<crate::models::DatasourceId>,
66}
67
68impl From<&crate::models::Package> for OutputPackage {
69    fn from(value: &crate::models::Package) -> Self {
70        Self {
71            package_type: value.package_type,
72            namespace: value.namespace.clone(),
73            name: value.name.clone(),
74            version: value.version.clone(),
75            qualifiers: value.qualifiers.clone(),
76            subpath: value.subpath.clone(),
77            primary_language: value.primary_language.clone(),
78            description: value.description.clone(),
79            release_date: value.release_date.clone(),
80            parties: value.parties.iter().map(OutputParty::from).collect(),
81            keywords: value.keywords.clone(),
82            homepage_url: value.homepage_url.clone(),
83            download_url: value.download_url.clone(),
84            size: value.size,
85            sha1: value.sha1.as_ref().map(|d| d.as_hex()),
86            md5: value.md5.as_ref().map(|d| d.as_hex()),
87            sha256: value.sha256.as_ref().map(|d| d.as_hex()),
88            sha512: value.sha512.as_ref().map(|d| d.as_hex()),
89            bug_tracking_url: value.bug_tracking_url.clone(),
90            code_view_url: value.code_view_url.clone(),
91            vcs_url: value.vcs_url.clone(),
92            copyright: value.copyright.clone(),
93            holder: value.holder.clone(),
94            declared_license_expression: value.declared_license_expression.clone(),
95            declared_license_expression_spdx: value.declared_license_expression_spdx.clone(),
96            license_detections: value
97                .license_detections
98                .iter()
99                .map(OutputLicenseDetection::from)
100                .collect(),
101            other_license_expression: value.other_license_expression.clone(),
102            other_license_expression_spdx: value.other_license_expression_spdx.clone(),
103            other_license_detections: value
104                .other_license_detections
105                .iter()
106                .map(OutputLicenseDetection::from)
107                .collect(),
108            extracted_license_statement: value.extracted_license_statement.clone(),
109            notice_text: value.notice_text.clone(),
110            source_packages: value.source_packages.clone(),
111            is_private: value.is_private,
112            is_virtual: value.is_virtual,
113            extra_data: value.extra_data.clone(),
114            repository_homepage_url: value.repository_homepage_url.clone(),
115            repository_download_url: value.repository_download_url.clone(),
116            api_data_url: value.api_data_url.clone(),
117            purl: value.purl.clone(),
118            package_uid: value.package_uid.to_string(),
119            datafile_paths: value.datafile_paths.clone(),
120            datasource_ids: value.datasource_ids.clone(),
121        }
122    }
123}
124
125impl TryFrom<&OutputPackage> for crate::models::Package {
126    type Error = String;
127    fn try_from(value: &OutputPackage) -> Result<Self, Self::Error> {
128        let mut parties = Vec::with_capacity(value.parties.len());
129        for p in &value.parties {
130            parties.push(crate::models::Party::try_from(p)?);
131        }
132        let mut license_detections = Vec::with_capacity(value.license_detections.len());
133        for d in &value.license_detections {
134            license_detections.push(crate::models::LicenseDetection::try_from(d)?);
135        }
136        let mut other_license_detections = Vec::with_capacity(value.other_license_detections.len());
137        for d in &value.other_license_detections {
138            other_license_detections.push(crate::models::LicenseDetection::try_from(d)?);
139        }
140        Ok(Self {
141            package_type: value.package_type,
142            namespace: value.namespace.clone(),
143            name: value.name.clone(),
144            version: value.version.clone(),
145            qualifiers: value.qualifiers.clone(),
146            subpath: value.subpath.clone(),
147            primary_language: value.primary_language.clone(),
148            description: value.description.clone(),
149            release_date: value.release_date.clone(),
150            parties,
151            keywords: value.keywords.clone(),
152            homepage_url: value.homepage_url.clone(),
153            download_url: value.download_url.clone(),
154            size: value.size,
155            sha1: value
156                .sha1
157                .as_ref()
158                .map(|s| crate::models::Sha1Digest::from_hex(s))
159                .transpose()
160                .map_err(|e| format!("invalid sha1: {}", e))?,
161            md5: value
162                .md5
163                .as_ref()
164                .map(|s| crate::models::Md5Digest::from_hex(s))
165                .transpose()
166                .map_err(|e| format!("invalid md5: {}", e))?,
167            sha256: value
168                .sha256
169                .as_ref()
170                .map(|s| crate::models::Sha256Digest::from_hex(s))
171                .transpose()
172                .map_err(|e| format!("invalid sha256: {}", e))?,
173            sha512: value
174                .sha512
175                .as_ref()
176                .map(|s| crate::models::Sha512Digest::from_hex(s))
177                .transpose()
178                .map_err(|e| format!("invalid sha512: {}", e))?,
179            bug_tracking_url: value.bug_tracking_url.clone(),
180            code_view_url: value.code_view_url.clone(),
181            vcs_url: value.vcs_url.clone(),
182            copyright: value.copyright.clone(),
183            holder: value.holder.clone(),
184            declared_license_expression: value.declared_license_expression.clone(),
185            declared_license_expression_spdx: value.declared_license_expression_spdx.clone(),
186            license_detections,
187            other_license_expression: value.other_license_expression.clone(),
188            other_license_expression_spdx: value.other_license_expression_spdx.clone(),
189            other_license_detections,
190            extracted_license_statement: value.extracted_license_statement.clone(),
191            notice_text: value.notice_text.clone(),
192            source_packages: value.source_packages.clone(),
193            is_private: value.is_private,
194            is_virtual: value.is_virtual,
195            extra_data: value.extra_data.clone(),
196            repository_homepage_url: value.repository_homepage_url.clone(),
197            repository_download_url: value.repository_download_url.clone(),
198            api_data_url: value.api_data_url.clone(),
199            purl: value.purl.clone(),
200            package_uid: crate::models::PackageUid::from_raw(value.package_uid.clone()),
201            datafile_paths: value.datafile_paths.clone(),
202            datasource_ids: value.datasource_ids.clone(),
203        })
204    }
205}