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