Skip to main content

provenant/output_schema/
package.rs

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