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