1use 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}