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