Skip to main content

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