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